Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Как в наследнике спрятать не виртуальный метод


Автор: Delphist 1.4.2009, 14:49
Есть класс:

Код

 TSomeClass = class
  ...
 public
  procedure Foo; 
  ...
 end;

Как мне в наследнике этого класса спрятать не виртуальный метод Foo в секцию private?, т.е.
Код

 TInheritClass = class(TSomeClass)
 private
   procedure Foo; 
  ...
 public
  ...
 end;

Если написать как я привел во втором коде, Delphi выдает ошибку.

Автор: Frees 1.4.2009, 14:54
Цитата(Delphist @  1.4.2009,  16:49 Найти цитируемый пост)
Если написать как я привел во втором коде, Delphi выдает ошибку.

а какую ошибку, у мя скомпилил без звука D2006

Автор: cemick 1.4.2009, 15:06
ИМХО это не возможно

Автор: Delphist 1.4.2009, 15:41
Цитата(Frees @  1.4.2009,  15:54 Найти цитируемый пост)
а какую ошибку, у мя скомпилил без звука D2006

Вот эту: E2065 Unsatisfied forward or external declaration: 'TInheritClass.Foo'

Приведи свой пример, ты походу в TInheritClass написал код для Foo:

Код

procedure TInheritClass.Foo;
begin
  inherited;
end;


А я спрашивал как это сделать, без объявления procedure TInheritClass.Foo;

Автор: Bose 1.4.2009, 15:48
Цитата(Delphist @  1.4.2009,  13:49 Найти цитируемый пост)
Если написать как я привел во втором коде, Delphi выдает ошибку.

Цитата(Delphist @  1.4.2009,  14:41 Найти цитируемый пост)
Вот эту: E2065 Unsatisfied forward or external declaration: 'TInheritClass.Foo'

это другая ошибка


Цитата(Delphist @  1.4.2009,  14:41 Найти цитируемый пост)
А я спрашивал как это сделать, без объявления procedure TInheritClass.Foo;

никак, смирись.

Автор: Delphist 1.4.2009, 16:26
Цитата(Bose @  1.4.2009,  16:48 Найти цитируемый пост)
никак, смирись.

А почему нельзя то, почему творцы Delphi запретили это?
Интересно, а С++ тоже этого не умеет?

Автор: cemick 1.4.2009, 16:31
Причем тут творцы, это ООП!

Автор: Delphist 1.4.2009, 19:10
Цитата(cemick @  1.4.2009,  17:31 Найти цитируемый пост)
Причем тут творцы, это ООП! 

C++ тоже не умеет?

Автор: bems 1.4.2009, 19:16
сделай публичный метод с таким же именем, который при вызове будет давать исключение

Автор: Beltar 3.4.2009, 07:15
Цитата

Интересно, а С++ тоже этого не умеет?


Я на Си++ не пишу, но насколько я помню из сравнительных разборов ООП в Си++ и Delphi, Си++ позволяет понижать видимость членам класса.

Добавлено через 7 минут и 51 секунду
А вообще, я честно говоря, не понял, зачем метод делать public, если в наследнике он уже не нужен и, может быть, даже опасен.

Автор: Delphist 3.4.2009, 09:38
Цитата(Beltar @  3.4.2009,  08:15 Найти цитируемый пост)
А вообще, я честно говоря, не понял, зачем метод делать public, если в наследнике он уже не нужен и, может быть, даже опасен. 

Чтобы дать понять, что класс наследник был предназначен строго для решения определенных задач в нем предоставляется только метод B, а метод Foo специально спрятан, чтобы не было иллюзии, что класс наследник еще выполняет и Foo.

Автор: Frees 3.4.2009, 09:45
зачем тогда вообще наследоваться?

наследование для расширения функционала а не для его уменьшения!

Добавлено через 12 минут и 57 секунд
может тебе делать подругому, скрыть в родителе все функции
а в потомнке открывать нужные

Автор: Alexeis 3.4.2009, 10:19
В С++ можно сделать Protected наследование.
Цитата

при protected-наследовании все спецификаторы остаются без изменения, кроме спецификатора public, который меняется на спецификатор protected (то есть public-члены базового класса в потомках становятся protected).


В делфи можно прятать и раскрывать свойства.

Автор: Delphist 3.4.2009, 10:20
Цитата(Frees @  3.4.2009,  10:45 Найти цитируемый пост)
может тебе делать подругому, скрыть в родителе все функции
а в потомнке открывать нужные 

Да все правильно, у меня многие наследники так и делают расширяют ф-цианал предка, но вот один наследник очень специфичен и делает только одну задачу, поэтому у него должен быть один public метод, а остальные в private, чтобы подчеркнуть что этот класс решают только конкретную задачу. Вы скажете "да напиши независимый класс без наследования" я отвечу НЕТ, потому как этот единственный public метод активно использует ядро предка для выполнения задачи которые на него возлагаются.

Автор: CodeMonkey 3.4.2009, 10:31
Цитата(Delphist @  3.4.2009,  10:20 Найти цитируемый пост)
этот единственный public метод активно использует ядро предка для выполнения задачи которые на него возлагаются.

И? Проблемы не видно.

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

И что же там мешает вызвать метод через приведение к предку?

P.S. IFWTPICPPTPICPP - "If you want to program in C++, then program in C++".

Автор: Alexeis 3.4.2009, 10:36
Цитата(CodeMonkey @  3.4.2009,  09:31 Найти цитируемый пост)
И что же там мешает вызвать метод через приведение к предку?

  Когда мы так делаем, то сами берем на себя ответственность, после такого компилятор "умывает руки". Изменение области видимости помогает избежать ошибок при работе с текущим классом. 

  Я не слышал такого чтобы в С++ можно было спрятать отдельный метод.

Автор: Delphist 3.4.2009, 11:15
Цитата(Alexeis @  3.4.2009,  11:36 Найти цитируемый пост)
Когда мы так делаем, то сами берем на себя ответственность, после такого компилятор "умывает руки". Изменение области видимости помогает избежать ошибок при работе с текущим классом. 

Alexeis, полностью с тобой согласен. 

_________
И вот все равно не понимаю почему нельзя понизить видимость метода в наследнике. Если кто-то скажет что это ООП, и там все логично, тогда я скажу а разве мой пример не логичен?

Автор: Alexeis 3.4.2009, 11:20
Можно сделать через Inherited, но объявить метод как inline, результат будет такой как нужно и синтаксически и бинарно.

Автор: CodeMonkey 3.4.2009, 11:49
Цитата(Delphist @  3.4.2009,  11:15 Найти цитируемый пост)
Изменение области видимости помогает избежать ошибок при работе с текущим классом. 

Вообще-то, как правильно уже заметили, это ошибка проектирования. Поэтому такая "фишка" - это костыль, помогающий решать эти проблемы. Может это и отлично ложиться в философию C/C++ ("мы дадим в руки программистам самые мощные инструменты, но они обязуются использовать их грамотно и во благо"), то уж точно не годится в Delphi.

Цитата(Delphist @  3.4.2009,  11:15 Найти цитируемый пост)
Если кто-то скажет что это ООП, и там все логично, тогда я скажу а разве мой пример не логичен?

Нет, не логичен. Вы допустили ошибку при создании класса TSomeClass и исправлять надо её, а не городить огород вокруг.

Автор: Alexeis 3.4.2009, 12:05
  Всего не предусмотришь, а менять реализацию уже работающих классов не лучший вариант.

Автор: Delphist 3.4.2009, 17:49
Цитата(Alexeis @  3.4.2009,  13:05 Найти цитируемый пост)
Всего не предусмотришь, а менять реализацию уже работающих классов не лучший вариант. 

ну да

Цитата(Alexeis @  3.4.2009,  12:20 Найти цитируемый пост)
Можно сделать через Inherited, но объявить метод как inline

в смысле сделать inherited

Автор: Alexeis 3.4.2009, 20:17
Цитата(Delphist @  3.4.2009,  16:49 Найти цитируемый пост)
в смысле сделать inherited 

Ну так как уже говорили с объявлением того же метода в наследнике, т.е. вот так
Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

 {$O-}

type
 TSomeClass = class
 public
   procedure Foo(val : Integer);
 end;

 TInheritClass = class(TSomeClass)
 private
   procedure Foo(val : Integer); inline;
 public

 end;

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }

  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TInheritClass }

procedure TInheritClass.Foo(val : Integer);
begin
  Inherited;
end;

{ TSomeClass }

procedure TSomeClass.Foo(val : Integer);
begin
  ShowMessage(IntToStr(val));
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  i : TInheritClass;
begin
  i := TInheritClass.Create;
  i.Foo(5);
end;

end.

Автор: Delphist 3.4.2009, 22:22
Цитата(Alexeis @  3.4.2009,  21:17 Найти цитируемый пост)
Ну так как уже говорили с объявлением того же метода в наследнике, т.е. вот так

Ааа, понял. ну что ж как вариант...

Автор: cemick 4.4.2009, 00:41
Цитата(Alexeis @  3.4.2009,  12:05 Найти цитируемый пост)
Всего не предусмотришь, а менять реализацию уже работающих классов не лучший вариант. 

Лучший вариант нагородить бредового кода в который без высоких сапог и резиновых перчаток лучше не суваться?

Автор: Alexeis 4.4.2009, 09:38
Цитата(cemick @  3.4.2009,  23:41 Найти цитируемый пост)
Лучший вариант нагородить бредового кода в который без высоких сапог и резиновых перчаток лучше не суваться? 

  Голословное и безосновательное утверждение попахивающее наездом. Я лично не видел кода 
Delphist. Вы его видели? Или судите так категорично обо всем только исходя из того что одна функция оказалась не в той области видимости?

Автор: cemick 4.4.2009, 13:40
Цитата(Alexeis @  4.4.2009,  09:38 Найти цитируемый пост)
 Голословное и безосновательное утверждение попахивающее наездом. Я лично не видел кода 
Delphist. Вы его видели? Или судите так категорично обо всем только исходя из того что одна функция оказалась не в той области видимости? 

Я не именно о варианте Делфиста, а вообще о подходе исправлять ошибки проективарония костылями. Мне кажется это не верный подход, который только запутывает код и многие вещи делает не очевидным. Если метод public  то он он паблик, и не надо мучатся почему в n-ом предке куда то пропал этот метод. Наличие таких возможностей чревато перегибами в его использование, по тому мне кажется что лучше, что бы таких возможностей вообще не существовало.
ЗЫ извини за наезд smile 

Автор: CodeMonkey 5.4.2009, 19:00
Поддерживаю cemick и полностью с ним согласен. Сам хотел такое написать, но опередили.

Автор: Alexeis 5.4.2009, 20:01
Цитата(CodeMonkey @  5.4.2009,  18:00 Найти цитируемый пост)
Поддерживаю cemick и полностью с ним согласен. Сам хотел такое написать, но опередили.

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

Добавлено через 3 минуты и 9 секунд
  Точно также как в свое время ввели дополнение класс хелпелпер, позволяющий безопасно расширить существующий класс не меняя код его реализации. Реальность такова что весь софт нуждается в поддержке и доработке, даже после ухода программиста, который его писал. В этом случае безопасность модификаций имеет первостепенное значение.

Автор: CodeMonkey 5.4.2009, 23:51
И чем же ушедший на пенсию программист мешает нам сменить видимость метода?

Автор: Alexeis 6.4.2009, 02:08
Цитата(CodeMonkey @  5.4.2009,  22:51 Найти цитируемый пост)
И чем же ушедший на пенсию программист мешает нам сменить видимость метода? 

  В теме же написано что от него поражаются и другие наследники, которые используют этот метод, если его скрыть они перестанут работать.
  Вот смотри есть класс TStream, который умеет читать и писать в абстрактный поток, для него есть TFileStream, который умеет реально читать и писать, но от TStream наследуется также TResourceStream, который писать не может по определению, однако ж методы записи у него унаследованы от TStream. Использовать их будет ошибкой программирования, хотя синтаксически компилятор съест. Борланд решил вопрос сгенерировав ошибку в run-time, это правильно если мы работаем с TResourceStream как с предком т.е. TStream, однако неверно при работе с TResourceStream, поскольку метод есть, компилируется верно, но при работе вызывает ошибку. Идеальным было бы скрыть в TResourceStream методы write, writeBuffer, copyfrom, поскольку они лишь путают, но не несут ни какой пользы. Но это не делается ввиду того что необходимый механизм скрытия методов попросту отсутствует. 

Автор: CodeMonkey 6.4.2009, 08:41
Цитата(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 в коде забыли их учесть.

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

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

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

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

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

Автор: CodeMonkey 6.4.2009, 10:12
Цитата(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 Найти цитируемый пост)
Такая фича не может быть потенциально опасной, потому что ее цель увеличить степень безопасности. 

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

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

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

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

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

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

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

 ?  smile 

Автор: cemick 6.4.2009, 14:58
Я думаю всем  понятно, чем проще код, тем он более понятен  и легко модифицируем и это может является показателям профессионализма. Увеличение энтропии всегда не хорошо,а добавление механизма сокрытия статических паблик методов добавлять много неоднозначностей. Часто говорится   что C++ мощный язык, но даже например перегрузка операторов собирает много критики. Вспоминается поговорка "заставь дурака богу молится дак он и лоб расшибет". Если вы не правильно спроектировали иерархию классов, можно воспользоваться средствами рефакторинга или можно натворить такого, что последующая модификация и развития проекта станет задачей архи сложной и не посильной, когда переписать все заново будет намного проще, чем что то исправить.  
Заметьте  множественно наследование считается злом, вы предлагаете что то похожее. ООП родилось не в мгновение ока, и  подменять принципы ООП не есть гуд. 

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

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

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

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

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

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

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

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

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

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

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

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

 smile 

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

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

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

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

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

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

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

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

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

Код

  A = class
  public
    procedure Test; virtual;
  end;

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



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

Автор: mes 7.4.2009, 01:16
cemick, нет слов ..   smile  чудеса smile 

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

Да, он с "любым методом" очень не красиво так делать. 

Автор: Alexeis 7.4.2009, 09:34
Цитата(cemick @  7.4.2009,  07:33 Найти цитируемый пост)
Да, он с "любым методом" очень не красиво так делать.  

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

Цитата(cemick @  6.4.2009,  15:46 Найти цитируемый пост)
Если например у нас иерархия состоит из 20 классов, то вы допускаете возможность в каждом классе менять область видимости как угодно? Или если была в одном классе видимость  изменена с  public на private, то в его наследниках он уже будет не видим?

  Невнимательно читаете, я говорил финальных классах. При правильном проектировании известно какие классы являются промежуточными, какие конечными. Недавно даже специальную директиву ввели final, для того чтобы пометить финальный класс. При попытке наследоваться от такого класса будет синтаксическая ошибка. В таком классе нужно прятать все лишнее. Если посмотреть в VCL перед финальным классом всегда есть промежуточный класс, который реализует 90-100% функционала финального класса (TCustomForm, TCustomEdit и т.д.), вот у него много чего открыто, а вот в финальном TForm, TEdit основные изменение это публикования одних свойств убирание других. Хотя от TForm, TEdit и можно наследоваться, но это весьма неудобно, поэтому для наследования смело берем TCustomForm, TCustomEdit.

Автор: cemick 7.4.2009, 10:37
ладно, уговорили  smile 

ыз хотя уверен что у бывших борладовских инженеров были причины сделать так, как есть  сейчас.

Автор: RinOSpro 7.4.2009, 15:36
Можно пометить в наследнике процедуру как deprecated конечто это не скроет ее, но будет высвечиватся красивым warning-ом smile

Автор: Delphist 8.4.2009, 09:26
Вообще пришлось в наследнике просто вызывать предка:
Код

TInheritClass = class(TSomeClass)
 private
   procedure Foo; 
  ...
 public
  ...
procedure TInheritClass.Foo;
begin
  inherited;
end;

 end;


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)