-
> Alkid © (15.01.09 12:26) [37] > > > oxffff © (15.01.09 11:02) [35] > > > > Смысл простой это вопрос идеалогии. [34] > > Я, вот, одного не понимаю - какой смысл разработчику создавать > экземпляр класса с абстрактными методами? Мне бы очень хотелось > бы узнать прецеденты, где какие-нибудь архитектурные задачи > решались через создание экземпляров абстрактных классов. > Пока же я твёрдо убеждён, что сама возможность так делать > - зло.
Существуют алтернативные мнения. [29] Задача инструмента предоставить выбор.
-
> Если в классе присутствуют абстрактные методы, то инстанцировать > класс нельзя, потому, что это ведёт к неминуемым ошибкам
unit 1.
TFoo = class (TObject)
public
constructor Create; virtual;
procedure DoSomething; virtual; abstract;
end;
TFooClass = class of TFoo;
TFooChild = class (TFoo)
public
procedure DoSomething; override;
end;
implementation
constructor TFoo.Create;
begin
inherited Create;
end;
procedure TFooChild.DoSomething;
public
... Чё-та делаем
end;
unit 2.
TMySuperPuperClass = class (....)
private
FFoo : TFoo;
public
constructor Create(FooClass : TFooClass);
property Foo : TFoo read FFoo;
end;
constructor TMySuperPuperClass.Create(FooClass : TFooClass);
begin
FFoo := FooClass.Create;
end;
unit 3
procedure Tform1.OnButton1Click(Sender : TObject)
begin
wtih TMySuperPuperClass.Create(TFooChild) do
begin
try
Foo.DoSomething;
finally
Free;
end;
end;
end;
-
XentaAbsenta © (15.01.09 12:44) [39] Выброси свой здравый смысл - конкретный наследник абстрактного класса может находиться в BPL и конструкция может выглядеть так: type
TFoo = class
protected
procedure Bar; abstract;
end;
TFooClass = class of TFoo;
.....
var
FooClass: TFooClass;
Foo: TFoo;
...
FooClass := GetFooClassFromExternalSource;
Foo := FooClass.Create;
... Мне было бы крайне любопытно узнать, как при компиляции данного кода проверить, является ли инстанцируемый класс абстрактным или содержит непереопределенные абстрактные методы
-
> Это не вопрос идеалогии, это вопро здравого смысла. Если > в классе присутствуют абстрактные методы, то инстанцировать > класс нельзя, потому, что это ведёт к неминуемым ошибкам, >
При наличии остуствия факт имеет место быть! Например виртуальные методы и все события - суть абстракция. Их при создании класса может и не быть.
-
> XentaAbsenta © (15.01.09 12:44) [39] > компилятор ... ни при > каких обстоятельствах не позволять инстанцировать класс даже через ссылку на класс
Штука в том, что компилятор дельфи в принципе не може этого знать в случае ссылки на класс. Ega23 © (15.01.09 12:55) [41] даже пример написал.
В синтаксисе С++ такого нет в приницпе, потому там все иначе.
-
> Ega23 © (15.01.09 12:55) [41] даже пример написал.
Ага мне особенно wtih понравился - зачем на такой вопрос такой подробный код ? Тем более, что есть ещё например AS.
-
> Игорь Шевченко © (15.01.09 12:57) [42] > класса может находиться в BPL и конструкция может выглядеть так:
Я никак не понимаю при чем тут BPL. В рамках одного проекта компилятор так же не в состоянии будет определить. Ну разве что прододумать логику поведения приложения на манер как определяются возможно неинициализируемые переменные, но и тут наверняка есть засада, когда это определить невозможно.
-
> Игорь Шевченко © (15.01.09 12:57) [42]
Всё просто - попытка инстанциировать абстрактный класс - исключительная ситуация. Т.е. позволять создавать экземпляр нельзя никак. Если нельзя проверить этот факт в Compile-time, надо проверять его в Run-Time. Но экземпляр абстрактного класса не должен получаться ни при каких обстоятельствах.
> oxffff © (15.01.09 12:51) [40]
В [29] описана ситуация с неправильно спроектированной структурой классов и "хакерский" подход при работе с ней. Данная практика, ИМХО, порочна, поскольку является раскладыванием граблей на будущее, что бы на них можно было самому потом смачно наступить, когда ты уже забудешь про свой гениальный ход. Ну или для ближнего своего грабля получится, когда он на это напорется.
По сути ты предлагаешь создать объект, который не выполняет опубликованного контракта (интерфейса). Это небезопасный ход, который требует от тебя постоянно держать в голове тот факт, что для данного объекта действует только часть интерфейса.
-
> Это небезопасный ход, который требует от тебя постоянно > держать в голове тот факт, что для данного объекта действует > только часть интерфейса.
Работу с VMT уже считают хакерским методом, а было время когда других способов и не было. То же OLE на позднем связывании и базируеться. В Objective-C или скриптовых все классы вообще тотальная абстракция - но работает же.
-
> Ага мне особенно wtih понравился - зачем на такой вопрос > такой подробный код ? Тем более, что есть ещё например > AS.
А чё не так? И as при чём?
-
> А чё не так? И as при чём?
По документации он безопастнее.
-
> По документации он безопастнее.
безопаснее ЧЕГО?
-
А вот такое имеет право на существование ?
unit Classes;
...
TStream = class(TObject)
private
...
public
function Read(var Buffer; Count: Longint): Longint; virtual; abstract;
function Write(const Buffer; Count: Longint): Longint; virtual; abstract;
function Seek(Offset: Longint; Origin: Word): Longint; virtual; abstract;
и TPointerStream = Class(TStream)
...
piblic
constructor Create(aP:Pointer;aSize:LongInt);
function Read(var Buffer; Count: Longint): Longint; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;
end;
причём я точно знаю, что Write никогда не будет использоваться.
-
> tesseract © (15.01.09 13:20) [48] > Работу с VMT уже считают хакерским методом, а было время > когда других способов и не было.
А вот отсюда поподробнее пожалуйста. Впервые слышу, что работа с VMT уже считается хакерским методом :) Что ты подразумеваешь по работой с VMT?
> То же OLE на позднем > связывании и базируеться. В Objective-C или скриптовых > все классы вообще тотальная абстракция - но работает же.
На позднем связывании вообще значительная часть полиморфизма работает. И VMT - это лишь один из вариантов механизма позднего связывания. Он эффективен по скорости выполнения, но зато сильно ограничен. Например, multiple dispatch на нём закачаешься делать.
Касаемо скриптовых языков - это от языка зависит. Да, есть "безклассовые" ОО-языки. Их ещё называют ОО с прототипированием. Но там есть свои остроумные способы разобраться с попыткой применить к объекту метод, который в нём (для него) не определён. К теме этого разговора это всё не имеет прямого отношения.
-
> причём я точно знаю, что Write никогда не будет использоваться.
ага, а также WriteBuffer и CopyFrom?
-
> безопаснее ЧЕГО?
Безопаснее прямого typecasting,
> А вот такое имеет право на существование ?
Это абстрактный класс перекрываемый наследниками. Abstarct error можно вызвать не напрягаясь, но дело не в этом.
-
> Ega23 (15.01.2009 13:32:51) [51]
Безопаснее приведения.
-
> По сути ты предлагаешь создать объект, который не выполняет > опубликованного контракта (интерфейса). Это небезопасный > ход, который требует от тебя постоянно держать в голове > тот факт, что для данного объекта действует только часть > интерфейса.
Во-первых, объект выполняет опубликованный интерфейс полностью. Просто у абстрактных методов реализация по умолчанию кидать exception. Я эту реализацию просто не меняю.
Во-вторых, ход как ход. Такой подход может быть полезным в разработке и в unit-тестах. Например, я создаю наследника от некоторого класса. Разработку веду по частям, вначале отлаживаю одну группу методов. Соответственно зачем мне вначале делать реализации всех абстрактных методов и помещать в каждый из них вызов raise ENotImplemented.Create() ???
В-третьих, это исключение можно ловить и обрабатывать. Т. е. использовать как часть логики. Дернули метод, получили EAbstractError, значит этот метод эту фичу не поддерживает. Или, по другому, опросили, что класс поддерживает. Узнали, что сортировка не поддерживается. Если все-таки вызвали метод Sort, то получили сигнал об ошибке---EAbstractError.
Как по мне, надо просто поменять точку зрения. В Delphi абстрактный метод имеет реализацию, это возбуждение исключения EAbstractError. Считай, что это вариант ENotImplemented. И используй. А чистых виртуальных методов а-ля С++ в Delphi нет.
-
> Безопаснее приведения.
Я не понял, а где у меня приведение (явное)?
-
> Я не понял, а где у меня приведение (явное)?
> wtih TMySuperPuperClass.Create(TFooChild) do
Прямо вот тут абсолютное приведение с моторчиком.
|