Форум: "Начинающим";
Текущий архив: 2011.04.10;
Скачать: [xml.tar.bz2];
ВнизКлассы Найти похожие ветки
← →
student_92 (2011-01-12 11:31) [0]нужно ли в конструкторе вызывать inherited Create
type
TMyClass = class(TObject)
{ ... }
public
{ ... }
constructor Create(const AItemName: string);
{ ... }
end;
constructor TMyClass.Create(const AItemName: string);
begin
inherited Create; // <- ?
{ ... }
end;
← →
Ega23 © (2011-01-12 11:33) [1]
> нужно ли в конструкторе вызывать inherited Create
Идеологически - нужно всегда. Вдруг у тебя предок изменится?
В данном конкретном случае - можно и не вызывать, ибо у TObject пустой невиртуальный конструктор.
Я всегда ставлю.
← →
student_92 (2011-01-12 11:35) [2]все ясн, спасибо
← →
Amoeba_ (2011-01-12 11:36) [3]Если наследование непосредственно от TObject, то вызов конструктора предка не является обязательным.
← →
Leonid Troyanovsky © (2011-01-12 21:47) [4]
> Ega23 © (12.01.11 11:33) [1]
> Идеологически - нужно всегда
Идеологически конструктору нужно быть виртуальным.
> Amoeba_ (12.01.11 11:36) [3]
> Если наследование непосредственно от TObject, то вызов конструктора
> предка не является обязательным.
И не обязательно class(TObject), можно просто - class.
--
Regards, LVT.
← →
KSergey © (2011-01-12 22:00) [5]В деструкторе тоже хорошо бы соотв. метод предка позвать, кстати!
← →
_Юрий (2011-01-12 22:08) [6]
> Leonid Troyanovsky © (12.01.11 21:47) [4]
> Идеологически конструктору нужно быть виртуальным.
>
Зачем?
← →
Leonid Troyanovsky © (2011-01-12 22:13) [7]
> _Юрий (12.01.11 22:08) [6]
> Зачем?
Подумать о потомках.
--
Regards, LVT.
← →
Ega23 © (2011-01-13 00:14) [8]
> Подумать о потомках.
Не вижу причин в надобности виртуального конструктора, кроме коллекции классов (class of)
Во всех остальных случаях точно также статичный метод через inherited можно вызвать.
Тебя ведь не удивляет вызов
function TObjectList.Add(AObject: TObject): Integer;
begin
Result := inherited Add(AObject);
end;
Никакой виртуальности, однако...
← →
Ega23 © (2011-01-13 00:24) [9]Или вот тоже
constructor TObjectList.Create(AOwnsObjects: Boolean);
begin
inherited Create;
FOwnsObjects := AOwnsObjects;
end;
← →
_Юрий (2011-01-13 00:26) [10]некоторым аналогом виртуализации конструктора TObject является конструкция
<T: class, construtor>. Но только для случаев определения типов в компайл-тайм
← →
Anatoly Podgoretsky © (2011-01-13 00:33) [11]> Ega23 (13.01.2011 00:14:08) [8]
Можно даже Result := inherited
← →
KSergey © (2011-01-13 09:27) [12]> Leonid Troyanovsky © (12.01.11 22:13) [7]
> Подумать о потомках
Потомки конкретного класса не будут конструироваться через фабрику. Никогда. Зачем о них думать? "пусть будет"?
← →
oxffff © (2011-01-13 09:42) [13]Если рассмотреть конструктор как экзмемплярный метод, то его виртуальность может быть полезна. Я не призываю делать так, я просто показываю, когда это может быть удобно вне полезности виртальности при классовом методе.
ClassA=class
constructor create;virtual;abstract;
end;
ClassB=class(ClassA)
constructor create;override;
end;
procedure TForm3.FormCreate(Sender: TObject);
var a:ClassA;
begin
a:=ClassB.create;
a.create;
a.free;
end;
← →
Ega23 © (2011-01-13 10:52) [14]
> oxffff © (13.01.11 09:42) [13]
А в чём прикол?
Ну, в смысле, назови задачу, где вот именно такая надобность в таком изврате?
← →
oxffff © (2011-01-13 11:05) [15]
> Ega23 © (13.01.11 10:52) [14]
>
> > oxffff © (13.01.11 09:42) [13]
>
>
> А в чём прикол?
> Ну, в смысле, назови задачу, где вот именно такая надобность
> в таком изврате?
Например переинициализация объекта без перевыделения памяти.
Например объект содержит некоторое состояние, теперь нужно перевести объект в начальное состояние без перевыделения памяти(это дорого).
Тут конечно на ум приходит отдельная procedure Initial, но если конструктор именно это и делает, то и нет надобности в отдельной Initial. Просто вызови экземпплярный конструктор.
← →
oxffff © (2011-01-13 11:06) [16]
> oxffff © (13.01.11 11:05) [15]
IMHO.
← →
Ega23 © (2011-01-13 11:07) [17]
> Тут конечно на ум приходит отдельная procedure Initial,
> но если конструктор именно это и делает, то и нет надобности
> в отдельной Initial. Просто вызови экземпплярный конструктор.procedure Init; virtual; возможно abstract;
constructor TFoo.Create;
begin
inherited;
Init;
end;
Всегда так и делал, нафига конструктор-то?
← →
oxffff © (2011-01-13 11:16) [18]
> Ega23 © (13.01.11 11:07) [17]
>
> > Тут конечно на ум приходит отдельная procedure Initial,
>
> > но если конструктор именно это и делает, то и нет надобности
>
> > в отдельной Initial. Просто вызови экземпплярный конструктор.
>
>
>
> procedure Init; virtual; возможно abstract;
>
> constructor TFoo.Create;
> begin
> inherited;
> Init;
> end;
>
> Всегда так и делал, нафига конструктор-то?
Нафига init? Просто Instance.create.
Ведь конструктор это и есть инициализатор.
P.S.
Просто у него при классовом вызове добавляется аллокатор.
← →
Ega23 © (2011-01-13 11:19) [19]
> Нафига init? Просто Instance.create.
А это к вопросу, нафига при наследовании от TObject inherited писать.
Сегодня одно, а завтра - другое. Добавится создание внутренних объектов, ещё какой-нибудь фигни.
Конструктор нужен для "выделения внутренней памяти", деструктор - для её зачистки. ИМХО.
← →
DiamondShark © (2011-01-13 11:51) [20]
> Ведь конструктор это и есть инициализатор.
Конструктор -- это конструктор, т.е. инициализатор из неинициализированного состояния.
Инициализатор из любого промежуточного состояния -- это не конструктор, это совсем другой метод, возможно, что с совершенно иной логикой работы.
Возможность вызова конструктора, как инстанс метода -- очевидная багофича языка, которая НИКОГДА не должна использоваться.
← →
oxffff © (2011-01-13 12:00) [21]
> DiamondShark © (13.01.11 11:51) [20]
>
> > Ведь конструктор это и есть инициализатор.
>
> Конструктор -- это конструктор, т.е. инициализатор из неинициализированного
> состояния.
> Инициализатор из любого промежуточного состояния -- это
> не конструктор, это совсем другой метод, возможно, что с
> совершенно иной логикой работы.
>
Помоему хорошо сказал в выделенном.
> Возможность вызова конструктора, как инстанс метода -- очевидная
> багофича языка, которая НИКОГДА не должна использоваться.
>
Китайский вопрос. А почему?
← →
Ega23 © (2011-01-13 12:07) [22]
> Китайский вопрос. А почему?
procedure Init; virtual; возможно abstract;
constructor TFoo.Create;
begin
inherited;
Init;
end;
да, можно обойтись, код из Init передать в конструктор. И реинициализировать вызовом конструктора.
constructor TFoo.Create;
begin
inherited;
FListField := TList.Create;
... <код, перенесённый из Init>
end;
И звиздец котёнку.
← →
DiamondShark © (2011-01-13 12:15) [23]
> Китайский вопрос. А почему?
Потому что русский язык велик и могуч. И читать на нём надо не по диагонали. Ответ у тебя прямо перед носом:
> Инициализатор из любого промежуточного состояния -- это
> не конструктор, это совсем другой метод, возможно, что с
> совершенно иной логикой работы.
Sapienti sat.
← →
oxffff © (2011-01-13 12:46) [24]
> DiamondShark © (13.01.11 12:15) [23]
>
> > Китайский вопрос. А почему?
>
> Потому что русский язык велик и могуч. И читать на нём надо
> не по диагонали. Ответ у тебя прямо перед носом:
>
> > Инициализатор из любого промежуточного состояния -- это
>
> > не конструктор, это совсем другой метод, возможно, что
> с
> > совершенно иной логикой работы.
>
> Sapienti sat.
Я лишь прочитал, что написано. Не больше, не меньше.
По остальному Вы трактуете свои слова как хотите.
Я так понимаю здесь идет намек на разницу в С++ между конструктором копий и оператором =. (на смысл этой оптимизации, отсутствие финализации lvalue)
А ничего что в Delphi в конструкторе может произойти исключение в конструкторе и вызывается деструктор, и что на самом деле есть еще newinstance который делает преинициализацию?
← →
oxffff © (2011-01-13 12:47) [25]
> да, можно обойтись, код из Init передать в конструктор.
> И реинициализировать вызовом конструктора.
>
>
> constructor TFoo.Create;
> begin
> inherited;
> FListField := TList.Create;
> ... <код, перенесённый из Init>
> end;
>
> И звиздец котёнку.
Заимствую упоминаемое ИШ выражение про стеклянный ....
← →
Cobalt © (2011-01-13 12:49) [26]2 oxffff © (13.01.11 12:00) [21]
В TStrings есть метод Create, а есть метод Clear
Используйте нужный
← →
oxffff © (2011-01-13 12:51) [27]
> Cobalt © (13.01.11 12:49) [26]
> 2 oxffff © (13.01.11 12:00) [21]
> В TStrings есть метод Create, а есть метод Clear
>
> Используйте нужный
Я написал не про то, что так нужно делать всегда, а про то, когда create и init идентичен по семантике и необходимости виртуального конструктора.
← →
Ega23 © (2011-01-13 12:57) [28]
> Я написал не про то, что так нужно делать всегда, а про
> то, когда create и init идентичен по семантике и необходимости
> виртуального конструктора.
Идентичен - да.
Хорошо, я по-другому переформулирую: ты сам бы написал такой код в коммерческом проекте?
← →
oxffff © (2011-01-13 14:13) [29]
> Ega23 © (13.01.11 12:57) [28]
>
> > Я написал не про то, что так нужно делать всегда, а про
>
> > то, когда create и init идентичен по семантике и необходимости
>
> > виртуального конструктора.
>
>
> Идентичен - да.
> Хорошо, я по-другому переформулирую: ты сам бы написал такой
> код в коммерческом проекте?
Я бы не стал писать так. Однако ничего плохого не вижу в этом стиле.
← →
oxffff © (2011-01-13 14:13) [30]
> Однако ничего плохого не вижу в этом стиле.
Точнее страшного.
← →
Ega23 © (2011-01-13 14:16) [31]
> Я бы не стал писать так. Однако ничего плохого не вижу в
> этом стиле.
Собственно, этим всё сказано.
Я бы тоже не стал. Именно по причине невозможности нормального масштабирования дерева классов.
← →
Cobalt © (2011-01-13 15:24) [32]Нет ничего плохого в том, чтобы забивать гвозди микроскопом :)
Задача выполнена? Выполнена.
Просто это выглядит странно.
← →
oxffff © (2011-01-13 16:03) [33]
> Cobalt © (13.01.11 15:24) [32]
> Нет ничего плохого в том, чтобы забивать гвозди микроскопом
> :)
> Задача выполнена? Выполнена.
> Просто это выглядит странно.
Забивать нужно с умом.
Если два метода семантически эквивалентны, то зачем спрашивается их два, а не один?
← →
DiamondShark © (2011-01-13 17:00) [34]
> Если два метода семантически эквивалентны
Они семантически не эквивалентны.
Они реализуют разные ветки перехода на графе состояний объекта.
← →
oxffff © (2011-01-13 17:20) [35]
> DiamondShark © (13.01.11 17:00) [34]
>
> > Если два метода семантически эквивалентны
>
> Они семантически не эквивалентны.
> Они реализуют разные ветки перехода на графе состояний объекта.
>
У кого как.
← →
DiamondShark © (2011-01-13 18:59) [36]
> oxffff © (13.01.11 17:20) [35]
> У кого как.
Ни у кого ни как.
По-определению, конструктор переводит объект из состояния "Выделен" в состояние "Инициализирован", а метод реинициализации переводит объект из любого промежуточного состояния в состояние "Инициализирован".
Иными словами, конструктор реализует одну единственную дугу графа состояний, а метод реинициализации должен реализовывать потенциально бесконечное множество дуг графа состояний. Даже в предельно примитивном случае, когда объект, кроме терминальных состояний, имеет только одно рабочее состояние, конструктор и реинициализатор реализуют разные дуги графа состояний. Даже если у тебя логика конструкции и реинициализации примитивны и вторая покравает первую, так, что тело конструктора сводится к единственному вызову реинициализатора, то это твой маленький секрет, деталь реализации, на которую клиент объекта ни в коем случае не имеет права полагаться.
Возможность вызова конструктора как метода -- это именно багофича конкретной реализации языка, появившаяся ради неусложнения компилятора. Никогда конструктор не задумывался как реинициализатор. Никакие объекты стандартной библиотеки не проектировались с возможностью использования конструктора как реинициализатора, никогда такой сценарий не документировался. Никогда такой сценарий не должен использоваться в новом дизайне, потому что нарушает привычные паттерны сложившейся практики, требует особого документирования, и, кроме вырожденных случаев, не даёт никакой экономии.
Наконец, вызывает большое сомнения сама необходимость реинициализации. Нет сценариев, в которых реинициализация дала бы преимущество перед повторной инстанциацией.
← →
_Юрий (2011-01-13 20:12) [37]а кто нибудь может формально доказать, почему при стиле программирования "состояние после инициализации не меняется никогда", количество ошибок в программе ощутимо снижается?
← →
DiamondShark © (2011-01-13 20:25) [38]
> _Юрий (13.01.11 20:12) [37]
Доказать такое формально нельзя.
Потому что понятие "ощутимо снижается" не имеет формального определения.
Но можно предположить, что ощутимо сужается пространство свободы для шаловливых ручонок.
← →
Ega23 © (2011-01-13 20:43) [39]
> Нет сценариев, в которых реинициализация дала бы преимущество
> перед повторной инстанциацией.
Полно. Сам недавно такую схему реализовывал.
← →
DiamondShark © (2011-01-13 20:51) [40]
> Ega23 © (13.01.11 20:43) [39]
> Полно.
Три примера найдёшь?
> Сам недавно такую схему реализовывал.
Давай посмотрим.
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2011.04.10;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.005 c