И ещё один глупый вопрос про сишарп - видимость методов

kruzer25

Я как-то привык, что код вида
abstract class BaseClass {
protected void foo {
//do something...
}
}
class DerivedClass : BaseClass {
private BaseClass obj;
public DerivedClass(BaseClass obj) {
this.obj = obj;
}
public void bar {
this.obj.foo;
}
}

должен работать, потому что видимости в php совершенно фиолетово, какие там объекты, она обращает внимание на классы; а на классы он обращает внимание только в той степени, что приватный метод должен быть определён в том же классе, откуда мы его зовём; а protected - в том же или в одном из родительских.
А в сишарпе такое не работает:
Cannot access protected member 'xxx.BaseClass.foo' via a qualifier of type 'xxx.BaseClass'; the qualifier must be of type 'xxx.DerivedClass' (or derived from it)
При этом, если вместо this.obj.foo написать DerivedClass)this.obj).foo то всё работает (про что и говорит сообщение об ошибке).
Может быть, я пишу не те ключевые слова?
Должен ведь быть способ реализовать следующее: есть несколько классов, унаследованных от одного базового, базовый определяет какой-то метод; этот метод не должен быть виден снаружи, но его должны уметь вызывать объекты этих классов друг у друга?

Dasar

Должен ведь быть способ реализовать следующее: есть несколько классов, унаследованных от одного базового, базовый определяет какой-то метод; этот метод не должен быть виден снаружи, но его должны уметь вызывать объекты этих классов друг у друга?
безопасность нарушается, т.е. если сделать как ты хочешь, то получится что можно вызывать вообще любой протектед метод любого объекта (главное чтобы его класс не был finalized с помощью вспомогательного wrapper-а, наследованного от класса атакуемого объекта.
в C# разделение доступа идет, как по классам, так и по экземплярам - и это правильно.
ps
то, что ты хочешь - можно сделать, через вспомогательный protected static метод у BaseClass-а

kruzer25

получится что можно вызывать вообще любой протектед метод любого объекта (главное чтобы его класс не был finalized с помощью вспомогательного wrapper-а, наследованного от класса атакуемого объекта
Хм, действительно.
Я как-то раньше не воспринимал области видимости как защиту от взломщиков, скорее - как дополнительную помощь программисту.
то, что ты хочешь - можно сделать, через вспомогательный protected static метод у BaseClass-а
Как-то трансанально :crazy:
ВпрочемЮ я уже придумал, как обойтись вообще без этого.
Кстати, а через reflection злобному хакеру разве не удастся вызвать хоть private-метод?

Dasar

Кстати, а через reflection злобному хакеру разве не удастся вызвать хоть private-метод?
только если у него к тому же есть права на доступ к закрытым полям.

zorin29

м-м-м, не нравится мне твое объяснение. В принципе, если стоит задача вызвать protected метод foo у некоего класса BaseClass, то всегда можно создать класс DerivedClass, и из него вызвать inherited foo. Соответственно, C# в этом случае защиту не обеспечивает.
Да и вообще, я не вижу сакрального смысла заботиться именно о "защите" класса от неправильного использования и порчи внутреннего состояния. Я считаю, что если есть исходник, и есть недобросовестный программист который ХОЧЕТ испортить объект, то ему никакие ограничения это сделать не помешают.
Скорее, "защита" нужна для того, чтобы пользователи класса не могли испортить объект СЛУЧАЙНО, в рамках предоставляемого интерфейса. Тогда public - это интерфейс, предоставляемый пользователю, а protected - интерфейс, предоставляемый наследнику.
Если я не прав, сорри.

kruzer25

всегда можно создать класс DerivedClass, и из него вызвать inherited foo.
Можно поподробнее?
Я считаю, что если есть исходник,
Исходника нет, есть сторонняя либа в .net-бинарниках. Что дальше?
Скорее, "защита" нужна для того, чтобы пользователи класса не могли испортить объект СЛУЧАЙНО, в рамках предоставляемого интерфейса.
Тогда становится непонятно, зачем нужна эта дополнительная защита по сравнению с PHP.

Dasar

м-м-м, не нравится мне твое объяснение. В принципе, если стоит задача вызвать protected метод foo у некоего класса BaseClass, то всегда можно создать класс DerivedClass, и из него вызвать inherited foo.
у своего собственнего экземпляра - да сможешь, но что тебе это даст?
у чужого экземпляра - нет, не получится.
Да и вообще, я не вижу сакрального смысла заботиться именно о "защите" класса от неправильного использования и порчи внутреннего состояния. Я считаю, что если есть исходник, и есть недобросовестный программист который ХОЧЕТ испортить объект, то ему никакие ограничения это сделать не помешают.
в чем отличие твоей фразы от?:
Да и вообще, я не вижу сакрального смысла заботиться именно о "защите" web-приложения(программы) от неправильного использования и порчи внутреннего состояния. Я считаю, что если есть исходник, и есть недобросовестный пользователь который ХОЧЕТ испортить web-приложение, то ему никакие ограничения это сделать не помешают.
я правильно все-таки понимаю, что ты считаешь, что целые приложения защищать надо?
но при этом считаешь, что отдельные объекты защищать не надо?
Я считаю, что если есть исходник, и есть недобросовестный программист который ХОЧЕТ испортить объект
здесь надо отличать порчу от возможности вызвать неадекватного поведения.
возьмем, например, ОС - да, пользователь с урезанными правами - может сделать так, что он больше своей учетной записью нормально пользоваться не сможет (ну, и фиг с ним главное - чтобы он не мог порушить работу самой ОС, или других пользователей.
так же и с объектами.
идеальная программа - должна быть построена так же, чтобы программист мог запороть только свои экземпляры, но не мог запороть работу основной части, или других модулей/экземпляров.
соответственно хороший framework - это тот, который позволяет такое поведение сделать.
.net такое поведение обеспечивает.
самое главное, я считаю, что не должно быть разделение между человеком и кодом, все что может сделано человек, должно быть доступно из кода, и наоборот.
поэтому если, например, на сайте или в программе, мы имеем возможность руками вызвать какую-то функцию, то мы должно иметь возможность вызвать эту функцию из кода снаружи, а в идеале, иметь возможность добавить свой код внутрь программы, который будет иметь возможность эту функцию вызывать.
возьмем, например, этот сайт - здесь, например, есть возможность загружать свои клиентские скрипты, но ведь часто бывает нужна возможность загрузить свой серверный скрипт(плагин а вот здесь уже как раз и нужны именно жесткие права на доступ из одного объекта в другой.

kruzer25

но ведь часто бывает нужна возможность загрузить свой серверный скрипт(плагин а вот здесь уже как раз и нужны именно жесткие права на доступ из одного объекта в другой.
Ага, унаследуем свой класс от DbConnection, передадим ему объект DbConnection, а он спросит oConnection.getPassword и выдаст на экран.

Dasar

Ага, унаследуем свой класс от DbConnection, передадим ему объект DbConnection, а он спросит oConnection.getPassword и выдаст на экран
не поможет.
передадим ему объект DbConnection
это чужой объект, к protected членам которого у тебя нет доступа

Dasar

и можно кстати просто запретить на уровне прав возможность обращения к DbConnection.

kruzer25

это чужой объект, к protected членам которого у тебя нет доступа
Я как раз про это, привожу примеры к твоей мысли ;)
Если бы было PHP-like поведение, то такой пользователь узнал бы пароль для доступа к БД; а так - не узнает.
Впрочем, имхо, было бы более логично как-нибудь помечать при сборке все классы, как финальные, кроме тех, которые явно определены как расширяемые.
Потому что, когда мы пишем класс в редакторе, можно понимать расширяемость в двух смыслах - расширяемость в рамках того же модуля (это должно быть разрешено по умолчанию и расширяемость другими разработчиками в их модулях (а вот это уже по умолчанию должно быть, наверное, всё-таки запрещено).

Dasar

Потому что, когда мы пишем класс в редакторе, можно понимать расширяемость в двух смыслах - расширяемость в рамках того же модуля (это должно быть разрешено по умолчанию и расширяемость другими разработчиками в их модулях (а вот это уже по умолчанию должно быть, наверное, всё-таки запрещено).
для этого и существует CAS
т.е., имхо, не надо смешивать техническую "закрытость" объекта и административную.
техническая закрытость - это мы собираем железку на клею, или на винтах, монолитно или на штекерах.
административная - это вешаем замок или нет.
protected, private - это техническая "закрытость".
cas - это административная "закрытость".
и их не стоит смешивать.

Vodnik

только если у него к тому же есть права на доступ к закрытым полям.
а можно здесь подробнее, что за права ему нужны?

Dasar

а можно здесь подробнее, что за права ему нужны?
данному куску кода должно быть выдано System.Security.Permissions.ReflectionPermission

Vodnik

а как это можно увидеть?
я вот создаю класс с private полем в одной сборке, а потом свободно меняю его в другой, я както неправильно компилирую?

klyv

пример в студию!

Vodnik

ну например
 
public class Class2
{
string Msg;
public Class2(string msg)
{
Msg = msg;
}
}

 
Class2 c = new Class2;
Type t = c.GetType;
FieldInfo fi = t.GetField("Msg", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
fi.SetValue(c, "123");
string msg = (string)fi.GetValue(c);

Dasar

а как это можно увидеть?
например,
1. запустить программу из сетевой шары другого компьютера
2. запустить прогу, как аплет в браузере
3. явно настроить permissions
Оставить комментарий
Имя или ник:
Комментарий: