К init или создать

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

Мой собственный порт кода Java является явным - необходимо назвать методы для сериализирования/десериализовывания. (Существуют тупики RPC, которые автоматически сериализируют/десериализуют, но никакая реализация RPC все же.)

проект Marc Gravell согласуется очень приятно с WCF, хотя - насколько я знаю, просто необходимо сказать ему (однажды) использовать буферы протокола для сериализации, и остальное прозрачно.

С точки зрения скорости, необходимо посмотреть страница сравнительного теста Marc Gravell. Мой код имеет тенденцию быть немного быстрее, чем его, но оба очень, намного быстрее, чем другие опции сериализации/десериализации в платформе. Нужно указать, что буферы протокола намного более ограничены также - они не пытаются сериализировать произвольные типы, только поддерживаемые. Мы собираемся попытаться поддерживать больше типов общих данных (десятичное число, DateTime и т.д.) портативным способом (как их собственные буферные сообщения протокола) в будущем.

5
задан Brad Gilbert 5 October 2009 в 16:52
поделиться

10 ответов

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

Если у вас есть отдельная процедура init (), которая должна быть вызываемый до того, как что-либо еще сработает, вызывающие с большей вероятностью проверит этот код возврата , чем вызовут метод didInitializationSucceed () после создания объекта.

3
ответ дан 18 December 2019 в 14:48
поделиться

Мне это не нравится. Мне кажется, что после постройки объект должен быть ... хорошо ... построен. Вместо этого этот код оставляет его в недопустимом состоянии, что почти никогда не бывает 1 .

1 Слово ласки вставлено для учета непредвиденных обстоятельств.

4
ответ дан 18 December 2019 в 14:48
поделиться

Двухэтапное построение обычно считается плохой идеей, если в классе есть методы, которые полагаются на то, что объект находится в некотором инициализированном состоянии. Как правило, я предпочитаю конструкторы, которые гарантируют, что объект находится в хорошем состоянии, или, если это невозможно сделать (возможно, потому, что некоторые аргументы конструктора были недопустимыми), генерировать исключение, поэтому никогда не существует экземпляров вашего класса, который является в плохом состоянии.

Требовать от потребителей вашего объекта помнить о вызове init () - плохая идея, потому что они этого не сделают.

2
ответ дан 18 December 2019 в 14:48
поделиться

Один из случаев, когда это может применяться, - это когда 'Foo' является атрибутом другого класса и не может быть полностью сконструирован до того, как будет создан родительский класс. Только тогда «Foo» можно «заполнить».

1
ответ дан 18 December 2019 в 14:48
поделиться

В некоторых языках (читай: C ++) вы не можете вызвать конструктор из другого конструктора, поэтому, если вам нужна общая часть нескольких конструкторов, вам нужно поместить ее в отдельный метод, и Я видел, как для этого использовалось имя init (). Но вы говорите не об этом?

1
ответ дан 18 December 2019 в 14:48
поделиться

Я считаю, что конструктор также должен выполнять часть init (). Если объект не построен полностью, его нельзя использовать.

Кроме того, инициализация в конструкторе позволяет использовать RAII. Основная идея RAII - представить ресурс локальным объектом, инициализировать его в конструкторе, чтобы деструктор локального объекта освободил ресурс. Таким образом, программист не может забыть освободить ресурс.

1
ответ дан 18 December 2019 в 14:48
поделиться

Я использую contructor и init, если создаю экземпляры объектов, основанных на вызове базы данных. Итак, если мне нужен пустой объект, чтобы я мог заполнить его, а затем сохранить в базе данных, я строю без параметров и не вызываю init (). В то время как, если мне нужно получить элементы объекта из базы данных, я contruct ($ param) и передам $ param в init ($ param)

.

1
ответ дан 18 December 2019 в 14:48
поделиться

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

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

0
ответ дан 18 December 2019 в 14:48
поделиться

Хотя это нельзя считать нормальным или предпочтительным способом создания объектов, при некоторых обстоятельствах это может быть подходящим способом. Например, вам может потребоваться создать объект только для указания его существования (в некотором списке, где счетчик имеет значение и т. Д.), Но инициировать его позже, только если этот конкретный объект используется впервые, поскольку инициализация всей коллекции объектов будет занимает много времени.

В этом случае полезно указать на то, что объект может быть не инициализирован, включив такой метод, как isInitialized () . Также таким образом вы можете передать инициализацию другому потоку, чтобы не блокировать основной поток приложения.

0
ответ дан 18 December 2019 в 14:48
поделиться

Разница в том, что инициализация происходит после вызова в конструктор суперкласса, но до того, как какой-либо код будет выполнен в вашем локальном конструкторе класса. Следовательно, это действительно зависит от ваших потребностей.

0
ответ дан 18 December 2019 в 14:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: