Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как в наследнике спрятать не виртуальный метод, из public в private 
:(
    Опции темы
CodeMonkey
Дата 6.4.2009, 08:41 (ссылка) |  (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89



Цитата(Alexeis @  6.4.2009,  02:08 Найти цитируемый пост)
  В теме же написано что от него поражаются и другие наследники, которые используют этот метод, если его скрыть они перестанут работать.

Ага, значит метод вызывать-таки можно и скрывать его будет неверным решением. В любом случае, никто не запрещает сделать InternalFoo для близко связанных классов. 

Цитата(Alexeis @  6.4.2009,  02:08 Найти цитируемый пост)
Идеальным было бы скрыть в TResourceStream методы write, writeBuffer, copyfrom, поскольку они лишь путают, но не несут ни какой пользы. Но это не делается ввиду того что необходимый механизм скрытия методов попросту отсутствует.

И это правильное решение. Вот создали мы TResourceStream. Окей, писать мы не можем. А потом мы передали его в процедуру Func1(AStrm: TStream), которая помимо кучи чтений (её обязательная работа) выполняет в самом конце одну запись - также обязательная часть её работы. И? Поток спокойно проглотит запись, т.к. теперь там не стоит возбуждение исключения. И это безопасно? Ладно, пусть там будет какое-то автогенерируемое исключение наподобие Abstract Error. Тогда всё равно получается, что от ситуации с возникновением исключения в run-time вы никуда не уйдёте, как было - так и осталось. Помимо путаницы (когда у нас метод невидим, когда он возбуждает исключение и т.п.) мы получаем лишние усилия разработчиков Delphi, которые можно было бы пустить в другое место.

Далее, пусть в классе вы запретили вызов метода предка, а у его потомка кто-то его снова включил. В какую-то процедуру передаётся класс с "погашенным методом". Вы передаёте туда класс-потомок, у которого метод повторно включён. Хотя метод есть, но вызвать вы его не можете. Опять какая-то нелогичность и путаница.

Замечу, что ситуация в целом несколько напоминает механизм абстрактных методов. Компилятор ведь не запрещает вам вызывать абстракный метод, уповая на то, что вы в run-time передадите экземпляр, где он реализован. Также и здесь. Уж если вы сделали метод public - вот любой его и сможет вызвать. А если вы его по какой-то причине не поддерживаете - ну так возбудите исключение. Это единообразно согласуется с общим поведением в Delphi. А вот это "скрытие методов" - IFWTPICPPTPICPP.

Вообще в C(++) понадобавляли много чего из серии "ааа... ну как же без этого, а ВДРУГ кому-то это понадобиться???". Из-за этого язык стал одним из самых мощных, гибких, но в то же время сложным и небезопасным. Дай людям в руки возможность и они обязательно воспользуются ей неправильно. Например, там есть возможность создать класс со статическим (не виртуальным) деструктором. И что? Допускаю, что когда-то кому-то такая возможность однажды пригодилась, но противовесом стали бесчисленные множества кривых реализаций со статическим деструктором вместо виртуального. В интернете куча статей и постов в блогах для таких вот горе-разработчиков: "почему деструктор ВСЕГДА должен быть виртуальным". А вот в Delphi он виртуален по-умолчанию. И проблем нет. А если он кому-то понадобиться - это не проблема как-нибудь сэмулировать.
Так же и эта вот возможность скрытия методов. Да, польза от неё может быть, но вреда намного больше.

P.S. Да, и это не единственный пример с исключениями в run-time, вот ещё, к примеру:
Код
type
  TSomeVar = (XXX, YYY, ...);
...
var
  SomeVar: TSomeVar;
...
  case SomeVar of
    XXX: ...
    YYY: ...
  ...
  else
    Assert(False, 'Design error');
  end;

Этот пример ловит ситуации, когда в тип переменной SomeVar мы добавили несколько новых констант, а в каком-то case в коде забыли их учесть.

Это сообщение отредактировал(а) CodeMonkey - 6.4.2009, 08:46


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Alexeis
Дата 6.4.2009, 09:39 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Цитата(CodeMonkey @  6.4.2009,  07:41 Найти цитируемый пост)

И это правильное решение. Вот создали мы TResourceStream. Окей, писать мы не можем. А потом мы передали его в процедуру Func1(AStrm: TStream), которая помимо кучи чтений (её обязательная работа) выполняет в самом конце одну запись - также обязательная часть её работы. И? Поток спокойно проглотит запись, т.к. теперь там не стоит возбуждение исключения. И это безопасно?

   Одно другому не мешает. Я точно не помню иерархию, но допустим, что TResourceStream наследуется не напрямую от TStream, а от промежуточного TReadOnlyStream, который генерит общее для всех потомков исключение WriteError. Теперь у TResourceStream есть необходимое поведение, но есть и лишние методы в секции public. Класс TResourceStream последний в цепочке, поэтому все лишние методы следует скрыть, так как же как скрываются свойства не имеющие смысла в контексте текущего класса.
  Такая фича не может быть потенциально опасной, потому что ее цель увеличить степень безопасности. 

Цитата(CodeMonkey @  6.4.2009,  07:41 Найти цитируемый пост)
Вообще в C(++) понадобавляли много чего из серии "ааа... ну как же без этого, а ВДРУГ кому-то это понадобиться???".

  Так в том то и прикол что и в С++ нет такого механизма...


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
CodeMonkey
Дата 6.4.2009, 10:12 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89



Цитата(Alexeis @  6.4.2009,  09:39 Найти цитируемый пост)
Так в том то и прикол что и в С++ нет такого механизма...

Ну не знаю, я в сях вообще 0  smile , но разве не об этом говорили:
Цитата(Alexeis @  3.4.2009,  10:19 Найти цитируемый пост)
В С++ можно сделать Protected наследование.

Цитата(Beltar @  3.4.2009,  07:15 Найти цитируемый пост)
 Си++ позволяет понижать видимость членам класса.


Цитата(Alexeis @  6.4.2009,  09:39 Найти цитируемый пост)
Одно другому не мешает. Я точно не помню иерархию, но допустим, что TResourceStream наследуется не напрямую от TStream, а от промежуточного TReadOnlyStream, который генерит общее для всех потомков исключение WriteError. Теперь у TResourceStream есть необходимое поведение, но есть и лишние методы в секции public. Класс TResourceStream последний в цепочке, поэтому все лишние методы следует скрыть, так как же как скрываются свойства не имеющие смысла в контексте текущего класса.

Я там не говорил о конкретно TResourceStream, но если брать пример с ним, то те мои слова остаются в силе, если предположить, что мы создаём наследника от TResourceStream у которого работают write-методы.

Цитата(Alexeis @  6.4.2009,  09:39 Найти цитируемый пост)
Такая фича не может быть потенциально опасной, потому что ее цель увеличить степень безопасности. 

Анти-пример (когда "такая фича" опасна, причём не только потенциально) я уже привёл ;) А второй аргумент против (тоже уже сказал) - это "маленькое улучшение" даётся за цену увеличения количества криворуких реализаций, в которых скрытие методов будет использоваться не по назначению. Именно поэтому моё мнение таково, что хак (исправление кривости дерева наследования) должен быть хаком, а не легализоваться на уровне языка.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Delphist
Дата 6.4.2009, 13:28 (ссылка)  | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphist Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2145
Регистрация: 3.2.2004
Где: всегда в сети

Репутация: 2
Всего: 3



Цитата(Alexeis @  6.4.2009,  03:08 Найти цитируемый пост)
 Идеальным было бы скрыть в TResourceStream методы write, writeBuffer, copyfrom, поскольку они лишь путают, но не несут ни какой пользы. Но это не делается ввиду того что необходимый механизм скрытия методов попросту отсутствует.  

Молодец Alexeis, удачный пример привел.


--------------------
ProcessInfo 1-ая моя программа (аналог spyxx.exe с гораздо большим функц-ом - внедрение dll в адр. простр. процесса, перехват API-функций, разбор приложения на окна мн.др).
Когда-то давным-давно использовал это...
PM MAIL ICQ   Вверх
mes
Дата 6.4.2009, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(Alexeis @  6.4.2009,  08:39 Найти цитируемый пост)

  Так в том то и прикол что и в С++ нет такого механизма... 

в cpp нельзя изменить область видимости метода в наследнике, я правильно понял цитату ? а как же это :
Код

class A
{
   public:
      void f() {..}
};
class B : public A
{
  private:
   using A::f;
};

 ?  smile 

Это сообщение отредактировал(а) mes - 6.4.2009, 14:29


--------------------
PM MAIL WWW   Вверх
cemick
Дата 6.4.2009, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 416
Регистрация: 6.7.2006
Где: Санкт-Петербург

Репутация: 2
Всего: 6



Я думаю всем  понятно, чем проще код, тем он более понятен  и легко модифицируем и это может является показателям профессионализма. Увеличение энтропии всегда не хорошо,а добавление механизма сокрытия статических паблик методов добавлять много неоднозначностей. Часто говорится   что C++ мощный язык, но даже например перегрузка операторов собирает много критики. Вспоминается поговорка "заставь дурака богу молится дак он и лоб расшибет". Если вы не правильно спроектировали иерархию классов, можно воспользоваться средствами рефакторинга или можно натворить такого, что последующая модификация и развития проекта станет задачей архи сложной и не посильной, когда переписать все заново будет намного проще, чем что то исправить.  
Заметьте  множественно наследование считается злом, вы предлагаете что то похожее. ООП родилось не в мгновение ока, и  подменять принципы ООП не есть гуд. 
PM MAIL WWW   Вверх
mes
Дата 6.4.2009, 15:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(cemick @  6.4.2009,  13:58 Найти цитируемый пост)
Вспоминается поговорка "заставь дурака богу молится дак он и лоб расшибет".

ага, дельфи в этом плане безопаснее, чем cpp. smile

имхо правильней(более применима к обсуждаемому контексту ) эта поговорка звучала бы при замене слова "заставь" на "позволь" smile
 
Цитата(cemick @  6.4.2009,  13:58 Найти цитируемый пост)
Увеличение энтропии всегда не хорошо,а добавление механизма сокрытия статических паблик методов добавлять много неоднозначностей. 

Ага, если метод все равно можно вызвать приведя к базовому классу, то смысла от прятанья его в наследнике в приват не много.
Поэтому лучше, если возможно, поступать обратно: наследоваться приватно, а нужные методы перенести в public зону.

Цитата(cemick @  6.4.2009,  13:58 Найти цитируемый пост)
Если вы не правильно спроектировали иерархию классов, можно воспользоваться средствами рефакторинга или можно натворить такого, что последующая модификация и развития проекта станет задачей архи сложной и не посильной, когда переписать все заново будет намного проще, чем что то исправить

Согласен, но не всегда возможно (по каким либо причинам) довести иерархию до идеала . smile


Это сообщение отредактировал(а) mes - 6.4.2009, 15:09


--------------------
PM MAIL WWW   Вверх
Alexeis
Дата 6.4.2009, 15:25 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Цитата(cemick @  6.4.2009,  13:58 Найти цитируемый пост)
Заметьте  множественно наследование считается злом, вы предлагаете что то похожее. ООП родилось не в мгновение ока, и  подменять принципы ООП не есть гуд.  

  Да ну, значит инкапсуляция теперь уже не принцип ООП? Объект предоставляет наружу, только то что допустимо к использованию, то что считает нужным и ничего лишнего. Текущий вариант как раз является нарушением принципа инкапсуляции. 
  Не надо думать что реализация ООП в Delphi это на 100% соответствие основным принципам. Это лишь жалкое подобие. Теоретическая концепция намного глубже.

Добавлено через 2 минуты и 16 секунд
Цитата(mes @  6.4.2009,  14:06 Найти цитируемый пост)
Ага, если метод все равно можно вызвать приведя к базовому классу, то смысла от прятанья его в наследнике в приват не много.

  Почему же, внутри функции можно сгенерировать исключение, а при прямом использовании будет ошибка этапа компиляции, что гораздо полезнее ошибки в рантайме.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
mes
Дата 6.4.2009, 15:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(Alexeis @  6.4.2009,  14:25 Найти цитируемый пост)
а при прямом использовании будет ошибка этапа компиляции, что гораздо полезнее ошибки в рантайме. 

да, но "не много" звучало в контексте того, что есть вариант получше :
Цитата(mes @  6.4.2009,  14:06 Найти цитируемый пост)
 лучше, если возможно, поступать обратно: наследоваться приватно, а нужные методы перенести в public зону.

 smile 



--------------------
PM MAIL WWW   Вверх
cemick
Дата 6.4.2009, 16:46 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 416
Регистрация: 6.7.2006
Где: Санкт-Петербург

Репутация: 2
Всего: 6



Цитата(Alexeis @  6.4.2009,  15:25 Найти цитируемый пост)
 Не надо думать что реализация ООП в Delphi это на 100% соответствие основным принципам. Это лишь жалкое подобие. Теоретическая концепция намного глубже.

Я этого и не говорил. Но если уже заговорили про это, то думаю лучше посмотреть как это реализовано в JAVA и С#..

Добавлено @ 16:52
Цитата(Alexeis @  6.4.2009,  15:25 Найти цитируемый пост)
 Текущий вариант как раз является нарушением принципа инкапсуляции.

пословицу смотреть выше 
smile 

Если например у нас иерархия состоит из 20 классов, то вы допускаете возможность в каждом классе менять область видимости как угодно? Или если была в одном классе видимость  изменена с  public на private, то в его наследниках он уже будет не видим?

и вообще бред какой то, хочешь менять область видимости делай virtual

Это сообщение отредактировал(а) cemick - 6.4.2009, 17:10
PM MAIL WWW   Вверх
mes
Дата 6.4.2009, 17:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(cemick @  6.4.2009,  15:46 Найти цитируемый пост)
и вообще бред какой то, хочешь менять область видимости делай virtual

да ?!  smile поясните пожалуйста  smile 


--------------------
PM MAIL WWW   Вверх
cemick
Дата 6.4.2009, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 416
Регистрация: 6.7.2006
Где: Санкт-Петербург

Репутация: 2
Всего: 6



Цитата(mes @  6.4.2009,  17:31 Найти цитируемый пост)
да ?!   поясните пожалуйста    

Код

  A = class
  public
    procedure Test; virtual;
  end;

 B = class(A)
  private
    procedure Test; override;
  end;



PM MAIL WWW   Вверх
Alexeis
Дата 6.4.2009, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



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


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
mes
Дата 7.4.2009, 01:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



cemick, нет слов ..   smile  чудеса smile 

Это сообщение отредактировал(а) mes - 7.4.2009, 01:21


--------------------
PM MAIL WWW   Вверх
cemick
Дата 7.4.2009, 08:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 416
Регистрация: 6.7.2006
Где: Санкт-Петербург

Репутация: 2
Всего: 6



Цитата(Alexeis @  6.4.2009,  22:36 Найти цитируемый пост)
cemick, только при этом нужно в наследнике вызывать метод предка. Тоже самое делается с любым методом, виртуальность тут ни при чем.

Да, он с "любым методом" очень не красиво так делать. 
PM MAIL WWW   Вверх
Страницы: (4) Все 1 2 [3] 4 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0875 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.