Дизайн абстрактного класса: почему бы не определить общедоступные конструкторы?

Посмотрите здесь (дизайн абстрактного класса): http://msdn.microsoft.com/en-us/library/ms229047.aspx

В нем говорится:

(1) Не определяйте общедоступные или защищенные внутренние (Protected Friend в Visual Basic) конструкторы в абстрактных типах.

В C# мы не можем создать экземпляр абстрактного класса. Итак, имеет ли все еще значение определение открытых конструкторов для абстрактных классов в C#? Или не писать открытые конструкторы для абстрактных классов из-за семантического значения?

Там также говорится:

(2) Определите защищенный или внутренний конструктор в абстрактных классах.

Определить внутренние конструкторы ?? В (1) он говорит нам, что отсутствие определения внутренних защищенных конструкторов связано с тем, что «конструкторы с общедоступной или защищенной внутренней видимостью предназначены для типов, которые могут быть созданы». Разве определение внутренних конструкторов для абстрактных классов не нарушает правила в (1)?

Заранее спасибо. :)


person Mouhong Lin    schedule 26.10.2010    source источник


Ответы (3)


Давайте рассмотрим каждый из случаев.

Рекомендуемые:

  • защищено — самый очевидный случай — все подклассы могут вызывать конструктор, независимо от того, в какой сборке они находятся (пока абстрактный базовый класс сам им виден). ).

  • внутренний – полезно, если вы хотите, чтобы абстрактный тип был видимым для всех, но не был наследуемым. В этом случае вы хотели бы сделать все неприватные конструкторы internal. Только подклассы внутри той же сборки, что и абстрактный базовый класс, смогут вызывать конструкторы — по сути, только они смогут наследовать. Другим вариантом использования может быть, если вам нужен «специальный» конструктор, который должен быть виден только для подклассов той же сборки.

  • private — используется в основном для конструкторов "грязной работы", на которые нацелены другие конструкторы абстрактного класса, когда он использует цепочку конструкторов. Единственное другое использование, когда все конструкторы являются закрытыми, заключается в разрешении создания подклассов только вложенными классами, которые имеют доступ к закрытым членам содержащего типа.


Не рекомендуется:

  • public — бесполезно, ведет себя идентично protected. В любом случае только подклассы могут вызывать конструктор, поскольку базовый класс является абстрактным.

  • защищенный внутренний — тоже ничем не отличается от protected. Уровень доступности protected internal означает защищенный ИЛИ внутренний, не защищенный И внутренний. Однако модификатор internal здесь не имеет смысла — он не предотвращает подклассы, находящиеся за пределами сборки, от вызова конструктора (при условии, что абстрактный базовый класс является общедоступным), поскольку они могут полагаться на доступ protected, а также позволяет ли он вызывать типы той же сборки, которые не являются подклассами (тип является абстрактным).

Ключевым моментом здесь является то, что каждый не-private конструктор в абстрактном классе уже в лучшем случае protected. Модификатор vanilla internal усиливает ограничения на то, кто может вызывать конструктор. public и protected internal ничего не делают, потому что кажется ослабляют ограничения, но на самом деле им это не удается.

person Ani    schedule 29.11.2010

В C# мы не можем создать экземпляр абстрактного класса. Итак, имеет ли все еще значение определение открытых конструкторов для абстрактных классов в C#? Или не писать открытые конструкторы для абстрактных классов из-за семантического значения?

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

Определить внутренние конструкторы ?? В (1) он говорит нам, что отсутствие определения внутренних защищенных конструкторов связано с тем, что «конструкторы с общедоступной или защищенной внутренней видимостью предназначены для типов, которые могут быть созданы». Разве определение внутренних конструкторов для абстрактных классов не нарушает правила в (1)?

Я считаю, что правило 1 касается public и protected internal, правило 2 касается protected и internal. Так что пересечения между ними нет.

person Armen Tsirunyan    schedule 26.10.2010
comment
Привет Армен. защищенный внутренний == защищенный + внутренний. Теперь, как задокументировано, защищенный конструктор — это хорошо, внутренний конструктор тоже в порядке, но почему защищенный + внутренний конструктор — это плохо? - person Mouhong Lin; 26.10.2010

Прошли годы. Думаю, теперь я лучше разбираюсь в этом вопросе. Поэтому я хотел бы добавить еще немного информации, помимо отличного ответа Ани.

В C# мы не можем создать экземпляр абстрактного класса. Итак, имеет ли все еще значение определение открытых конструкторов для абстрактных классов в C#?

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

Определить внутренние конструкторы ?? В (1) он говорит нам, что отсутствие определения внутренних защищенных конструкторов связано с тем, что «конструкторы с общедоступной или защищенной внутренней видимостью предназначены для типов, которые могут быть созданы». Разве определение внутренних конструкторов для абстрактных классов не нарушает правила в (1)?

Если мы хотим, чтобы абстрактный класс наследовался только подклассами внутри одной сборки, очевидно, мы не можем использовать protected (иначе он может наследоваться вне сборки). Теперь у нас есть несколько вариантов выбора:

  • общедоступный. Как упоминалось выше, public вводит в заблуждение читателей кода. Не используйте его.

  • private. Мы хотим, чтобы абстрактный класс наследовался подклассами внутри одной сборки, а не только вложенными подклассами, поэтому private не будет работать.

  • защищенный внутренний — он нам никогда не понадобится, потому что он ничем не отличается от protected.

  • внутренний — это вводит в заблуждение читателей кода, но у нас нет другого выбора. Я бы подумал, что это компромисс.

person Mouhong Lin    schedule 22.04.2015