2013-03-27 3 views
1

Я прихожу из мира PHP, и мне любопытно, почему разработчики выбирают способ добавления конструктора (с аргументом) к наследованию. По моему мнению, он нарушает принцип DRY, повторяя много кода, в зависимости от структуры. Я сделал небольшое исследование - PHP, Ruby, Python наследует конструктор. Java, C#, C++ нет. C++ 0x имеет новую функцию, явно определяющую наследования.Почему Dart не наследует конструктор?

Итак, есть ли какие-либо преимущества для программиста, у которого нет наследуемого конструктора и явно писать конструктор снова и снова?

+1

его заставляет вас научиться печатать быстрее ... –

ответ

3

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

Так что если вы хотите, чтобы создать какой-то объект, как это:

public class Foo { 
    private final String bar; 

    public Foo(String barValue) { 
     this.bar = barValue; 
    } 
} 

Вы бы остались с некоторой неопределенностью относительно того, что происходит, когда кто-то назвало конструктором нулевого параметра родителя:

Foo bla = new Foo(); // runtime error or is bar null? 

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

В конце концов, я думаю, что все сводится к философии: php, ruby ​​и т. Д., Идет в направлении меньшего набора текста, где java, C#, дротик и т. Д., Как правило, идут в сторону большего печатать и меньше места для путаницы.

4

Я не был полностью доволен объяснением Мейсона, поэтому я сделал небольшое исследование.

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

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

Эта проблема часто возникает в рамках различных типов, где часто часть API-интерфейса фреймворка состоит из классов, которые вы ожидаете расширить, или абстрактных классов для реализации - если подписи конструктора меняются в рамках класс, вы бы наследовали те изменения, которые большую часть времени не имеют смысла. Это называется проблемой «Fragile Base Class».

Вторая причина - более философская сторона и тесно связана с первым. Конструкторы определяют, что ваш класс требует от вас, как потребителя этого класса, когда вы создаете экземпляр - так что о требуется самого класса. Сравните это с методами, которые определяют фактическое поведение класса - это то, что делает класс . Исходя из этого, философский аргумент состоит в том, что наследование составляет примерно поведение, а не о .

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

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

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

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

В отличие от слепого наследования потребностей базового класса, без активного демонстрации каких-либо соображений относительно соответствия потребностей базового класса требованиям расширенного класса.

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

Смежные вопросы