Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
15-1293035423
Dimka Maslov
2010-12-22 19:30
2011.04.10
Опять про физику


15-1293223383
Stenfit
2010-12-24 23:43
2011.04.10
перевод


15-1293519707
12
2010-12-28 10:01
2011.04.10
Уходя от DBAware, зашился. Что можно мне посоветовать?


15-1293027819
картман
2010-12-22 17:23
2011.04.10


2-1294659014
User
2011-01-10 14:30
2011.04.10
Программа вылетает, если переменная принадлежит классу.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский