OberonCore
https://forum.oberoncore.ru/

Терминологический спор. Что такое конструктор?
https://forum.oberoncore.ru/viewtopic.php?f=23&t=4326
Страница 1 из 2

Автор:  Иван Кузьмицкий [ Среда, 24 Апрель, 2013 16:31 ]
Заголовок сообщения:  Терминологический спор. Что такое конструктор?

Мёссенбок пишет, что конструктор - это "порождающий паттерн" (Приёмы проектирования в Обероне-2 и Компонентном Паскале):
Цитата:
При создании объекта желательно инициализировать его поля. Если вы не желаете забыть об инициализации, разумно будет объединить создание и определение в одно действие. Для этого и существует шаблон "конструктор"

Можно ли данную процедуру назвать конструктором?

Код:
TYPE
   DropValue* = POINTER TO RECORD (Value)
      val*: Dialog.List;
      data: ListsMap.IntMap;
   END;

PROCEDURE NewDropValue*(): DropValue;
   VAR dv: DropValue;
BEGIN
   NEW(dv); dv.val.index:=keepSel; RETURN dv
END NewDropValue;


Проблема в том, что тип DropValue не LIMITED, а значит, при создании объекта клиентам модуля можно обходиться без NewDropValue. Если эта процедура необязательна к использованию, можно ли сказать, что это уже формально не конструктор, а просто "утилитарная функция"?

Автор:  Valery Solovey [ Среда, 24 Апрель, 2013 17:58 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

Я бы сказал, что конструктор - это инструмент, используемый на определённом участке жизненного цикла объекта. Одни языки созданы таким образом, что для прохождения данного участка жизненного цикла использование данного инструмента необходимо, а другие языки - нет.

Автор:  Иван Кузьмицкий [ Среда, 24 Апрель, 2013 18:28 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

Даже если язык не поддерживает напрямую понятие конструктора, то, по-моему, процедура, порождающая объект и инициализирующая его поля, определённо является конструктором. Вполне, так сказать, формальные признаки.

Автор:  Valery Solovey [ Среда, 24 Апрель, 2013 18:51 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

Да, я тоже так думаю.

Автор:  Пётр Кушнир [ Среда, 24 Апрель, 2013 20:18 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

По определению, конструктор это метод класса и вызывается ПРИ создании экземпляра, а не ДЛЯ его создания.
Поэтому получается, что в языках с конструкторами сначала new, а потом вызов конструктора.
Иначе пришлось бы new назвать конструктором. Ну, породил, значит "конструктор".
А в обероне вообще нет конструкторов, поэтому Мессенбёк имитирует работу среды по вызову конструктора, с помощью процедуры модуля.
Код:
TYPE
   T* = POINTER TO RECORD
      a- : REAL
   END;

PROCEDURE ( t : T ) InitT* ( x : REAL );
   BEGIN
      t.a :=x
END InitT;

PROCEDURE NewT* ( x : REAL ) : T;
   VAR t : T;
   BEGIN
      NEW(t); t.InitT(x);
      RETURN t
END NewT;

И здесь конструктором является метод InitT, который и нужен только потому, что поле класса только для чтения (что вполне обосновано). Рассуждения об удобстве такого решения можно оставить за скобками.

Автор:  Пётр Кушнир [ Среда, 24 Апрель, 2013 20:22 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

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

А вообще, чем точнее воспроизводить код, которым демонстрируют паттерн, тем больше уверенности, что ваш код можно будет обозвать по имени паттерна, а не "вольным пересказом перевода".

Автор:  Иван Кузьмицкий [ Среда, 24 Апрель, 2013 20:28 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

Пётр Кушнир писал(а):
По определению, конструктор это метод класса и вызывается ПРИ создании экземпляра, а не ДЛЯ его создания.
По чьему определению? Я привёл определение Мёссенбока, которое раскрывает суть, а не ограничивает форму. И не зависит от используемого языка.

Пётр Кушнир писал(а):
И для статических рекордов свойство "порождения" рекорда не имеет смысла, но метод .Init вполне может называться конструктором.
Это вряд ли возможно, использовать столь размытую терминологию.

Автор:  Madzi [ Среда, 24 Апрель, 2013 22:29 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

Если ПРИ создании - то конструктор,
А если ДЛЯ создания - то фабрика.

Автор:  Иван Кузьмицкий [ Среда, 24 Апрель, 2013 23:26 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

Пётр Кушнир писал(а):
По определению, конструктор это метод класса и вызывается ПРИ создании экземпляра, а не ДЛЯ его создания. Поэтому получается, что в языках с конструкторами сначала new, а потом вызов конструктора.
Иначе пришлось бы new назвать конструктором. Ну, породил, значит "конструктор".
new - это аллокатор же, если скалькировать слово напрямую. А конструктор, по определению, приводит свежесозданный объект в допустимое состояние. В Object Pascal вызов аллокатора синтаксически совмещён с конструктором, в джаве и др. тоже (имя конструктора должно совпадать с именем класса), но всегда конструкторы связаны с двумя аспектами - создание объекта и приведение его в допустимое состояние. Конструктор как метод класса - так это же просто способ языковой реализации, как же ещё установить связь между конструктором и классом? Пришпандорили как метод, да и всё тут.

Посмотрел, как конструкторы реализованы в джаве, питоне, С++ и дельфи. Везде инициализация полей привязана к созданию объекта. То есть, языковый конструктор есть, по факту, реализация паттерна Конструктор. Надо разводить паттерн и языковую реализацию.

Автор:  Valery Solovey [ Четверг, 25 Апрель, 2013 00:16 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

Не надо их разводить. Это логичное решение: не забываешь произвести инициализацию объекта. Между действиями выделения места в ОЗУ и инициализации с объектом ничего делать нельзя. Соответственно, обе эти вещи обязаны идти друг за другом. Объединение их в одно целое исключает вероятность ошибки в данном месте.

А у нас они не объединены потому, что строятся на основе записи, а запись не обязана инициализироваться конструктором.

Автор:  Иван Кузьмицкий [ Четверг, 25 Апрель, 2013 06:57 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

Я имел в виду, что есть паттерн Конструктор как носитель смысла, и есть языковая реализация, которая есть форма. Содержание понятия Конструктора не определимо через его реализацию, поэтому я и считаю, что надо разводить паттерн и реализацию.

Автор:  Александр Ильин [ Четверг, 25 Апрель, 2013 08:58 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

Иван Кузьмицкий писал(а):
Я имел в виду, что есть паттерн Конструктор как носитель смысла
Я считаю, что нет паттерна Конструктор, а есть паттерн Фабрика. А Конструктор - это языковой механизм, который где-то присутствует, а где-то отсутствует.

В КП нам предлагают отсутствующие конструкторы компенсировать использованием фабрик.

Автор:  Иван Кузьмицкий [ Четверг, 25 Апрель, 2013 09:50 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

Не соглашусь. Паттерн Конструктор есть, и он описан у Мёссенбока, как и Фабрика у него же и у GoF. Фабрика и конструктор - разные паттерны, и это видно из описаний.

У Мёссенбока,
Цитата:
Назначением шаблона проектирования "фабрика" является создание объектов в условиях, где динамический тип объекта заранее неизвестен

У GoF есть два паттерна - абстрактная фабрика и фабричный метод, которые решают ту же проблему - создание объекта, тип которого определяется в рантайме.

Правда, у GoF понятие "конструктор" отождествляется с операцией (метод) в С++, которая есть автоматический инициализатор. Но это проблема гофов, я считаю :)

P.S. В языке Go убрана реализация паттерна конструктор. Как всегда, майнстрим подпитывается правильными оберон-идеями :)
https://sites.google.com/site/gopattern ... nstructors
Цитата:
Go doesn't support constructors, but constructor-like factory functions are easy to implement:

Автор:  Иван Кузьмицкий [ Понедельник, 06 Май, 2013 14:08 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

Чтобы закрыть тему, попытался разобраться в онтологии понятия "конструктор". Для этого пошарил в документации к PHP, Python, C++, C#, Java (тут и тут), Smalltalk, Free Pascal и даже PascalABC.NET. Не обошлось без Гради Буча.

Все источники, как один, связывают смысл конструктора с порождением экземпляра класса и приведением его в допустимое состояние. Кто-то прямо говорит, что конструктор создаёт новый объект, кто-то ставит вызов конструктора сразу после new так, что вы не можете создать объект, не вызвав конструктора. Но никто не рассматривает конструктор как операцию, отдельную от порождения объекта.

Таким образом, мы имеем дело со схемой, не зависящей от языка программирования и состоящей из двух операций:
1) Порождение объекта (экземпляра класса)
2) Инициализация атрибутов объекта (приведение в допустимое состояние).

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

Дальше мы смотрим, как эта схема формализуется в разных ЯП. Естественно, по-разному. Либо это функция, возвращающая в качестве результата ссылку на созданный объект, либо метод инициализации, вызываемый автоматически, сразу после создания объекта обычным способом.

Отсюда вывод, даже два.

Первый: конструктор - это в первую очередь, паттерн проектирования, а не элемент описания ЯП. На языке Component Pascal конструктор реализуется (не "имитируется", а именно реализуется) очевидным и простым способом (указанным в одном из предыдущих сообщений).

И второй. Когда говорят, что в Обероне нет конструкторов, то всего лишь имеют в виду отсутствие поддержки паттерна в формальном описании языка, только и всего. Это совершенно не мешает использовать конструкторы в Оберонах.

Автор:  kemiisto [ Четверг, 14 Апрель, 2016 15:07 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

Конструктор - это паттерн

Согласен с Иваном Кузьмицким: конструктор - это действительно паттерн. Паттерн создания экземпляра класса (объекта) (instantiation), который состоит из последовательного выполнения двух шагов:
  • Выделения памяти (allocation).
  • Инициализации (initialization).
В большинстве популярных языков этот паттерн действительно оформлен в отдельный языковой конструкт, но, замечу, что не во всех. Скажем, в Objective-C, создание объекта осуществляется явным последовательным вызовом двух методов с говорящими именами alloc и init:
Код:
Foo *f = [[Foo alloc] init];
При этом существует и метод new (конструктор как отдельный языковой конструкт), который объединяет действия alloc и init:
Код:
Foo *f = [Foo new];
однако, его использование считается менее предпочтительным, потому что он, во-первых, не поддерживает различные дополнительные инициализаторы (initWithString там всякие), а во-вторых, считается менее наглядным.

Конструктор требует дисциплины, если не облачён в отдельный конструкт

Так же отмечу, что приведённая выше в качестве примера идиома alloc-init из Objective-C, которая суть есть реализация паттерна "конструктор", требует определённой дисциплины от программиста. Например, язык в принципе позволяет только выделить память под объект, не инициализируя его,
Код:
Foo *f = [Foo alloc];
поэтому программист обязан до автоматизма заучить суть паттерна "конструктор": создание экземпляра класса = выделение памяти + инициализация (instantiation = allocation + initialization). Или ещё пример: метод init в подклассе сначала обязан вызывать метод init родительского класса:
Код:
- (id)init {
    self = [super init];
    ...
    return self;
}
И все эти правила по сути, конечно, не что иное, как составные части паттерна "конструктор".

Автор:  kemiisto [ Четверг, 14 Апрель, 2016 15:14 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

И ещё по поводу дисциплины. Можно, конечно, как предлагает Мёссенбёк в третьем издании Objektorientierte Programmierung in Oberon-2 (см. код Петра Кушнира), определять для типа T метод NewT в качестве одного единственного метода, ответственного за реализацию паттерна "конструктор". Но я бы тут дважды подумал, а стоит ли так делать?

Возможно, стоит ограничиться только инициализатором InitT и дисциплиной вызова InitT(t) после NEW(t) в клиентском коде, как всё тот же Мёссенбёк предлагал во втором издании всё того же опуса Object-Oriented Programming in Oberon-2 (см. раздел 8.1 Initialization of Objects). И не столько потому, что теряется наглядность, сколько потому, что всё равно остаётся возможность только выделить память посредством NEW без последующей инициализации. В КП для определённого типа записей (LIMITED), конечно, NEW запрещён за пределами определяющего модуля, но, во-первых, это касается только LIMITED-записей, а во-вторых, в Oberon-2 таких средств, вроде бы, вообще нет. Так что от дисциплины всё-равно никуда не деться: следует всегда создавать экземпляр класса T, используя обязательно определённый его создателем конструктор NewT, а не посредством NEW. С другой стороны, с конструктором NewT делаются возможными определённые вещи, невозможные с иcпользованием идиомы NEW-InitT, так что может Мёссенбёк и прав. :)

Автор:  prospero78 [ Четверг, 14 Апрель, 2016 15:16 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

Цитата:
Если ПРИ создании - то конструктор,
А если ДЛЯ создания - то фабрика.

Мадзи, 100%. Плюсую.
Цитата:
new - это аллокатор же,

Иван! Порадовал)
Цитата:
Не надо их разводить. Это логичное решение: не забываешь произвести инициализацию объекта.

Незачёт, Валера. Тут Ваня Денисов задачу с массивом задачу решал. Зачем инициализировать его, если это сделает внешняя либа?
Цитата:
Я считаю, что нет паттерна Конструктор, а есть паттерн Фабрика.

Не согласен с тобой, Алексей, и далее поддерживаю позицию Ивана.
Цитата:
Таким образом, мы имеем дело со схемой, не зависящей от языка программирования и состоящей из двух операций:
1) Порождение объекта (экземпляра класса)
2) Инициализация атрибутов объекта (приведение в допустимое состояние).

Автор:  kemiisto [ Четверг, 14 Апрель, 2016 15:21 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

Madzi писал(а):
Если ПРИ создании - то конструктор,
А если ДЛЯ создания - то фабрика.

Нет, не так.
Если ПРИ создании - то инициализатор,
А если ДЛЯ создания - то конструктор или фабрика, в зависимости от того, какой шаблон создания объекта выбран.

Автор:  prospero78 [ Четверг, 14 Апрель, 2016 15:24 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

Цитата:
Если ПРИ создании - то инициализатор,

Это и есть конструктор.

Автор:  kemiisto [ Четверг, 14 Апрель, 2016 15:37 ]
Заголовок сообщения:  Re: Терминологический спор. Что такое конструктор?

prospero78 писал(а):
Цитата:
Если ПРИ создании - то инициализатор,

Это и есть конструктор.

Нет. Ещё раз повторю, конструктор = аллокатор + инициализатор, где конструктор - прежде всего паттерн, а аллокатор и инициализатор - процедуры/методы. Конструктор можно реализовать как отдельный метод, но это не существенно.

На примере:
Код:
VAR
  f: Foo;
BEGIN
  NEW(f); InitFoo(f);
END;
Здесь процедура NEW - аллокатор, процедура InitFoo - инициализатор, а конструктор - всего навсего паттерн последовательного вызова этих двух процедур для создания экземпляра класса Foo. Можно оформит конструктор и в отдельную процедуру, но сути дела это не меняет.

Более-менее подробно будет так: если процедура/метод используется
  • для выделения памяти - то это аллокатор (NEW);
  • для инициализации объекта при его создании - то инициализатор (InitFoo),
  • для создания объекта (включающего и выделения памяти, и инициализацию) - то конструктор (ну или фабрика) (NewFoo, если таковой определён).

Страница 1 из 2 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/