Зачем закрывать класс?

Я хотел бы услышать, что является мотивацией для большинства закрытых классов в инфраструктуре .Net. В чем преимущество герметизации класса? Я не могу понять, как нельзя позволить наследование быть полезным и, скорее всего, не единственным, кто сражается с этими классами.

Итак, почему инфраструктура спроектирована таким образом, и разве это не было бы неустранимым изменением, чтобы вскрыть все? Должна быть другая причина, но только быть злым?

Ответ 1

  • Иногда классы слишком ценны и не предназначены для наследования.
  • Runtime/Reflection может делать предположения о наследовании о закрытых классах при поиске типов. Отличным примером этого является: Атрибуты рекомендуется запечатывать для скорости выполнения поиска. type.GetCustomAttributes(typeof (MyAttribute)) будет выполнять значительно быстрее, если MyAttribute запечатан.

Статья MSDN для этого раздела Ограничение расширяемости с помощью классов герметизации.

Ответ 2

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

  • Он может определить вашу реализацию (вы должны объявить, какие методы собираются вызывать, какие другие методы, в случае, если пользователь переопределяет один, а не другой).
  • Он показывает вашу реализацию, а не только эффекты
  • Это означает, что при проектировании необходимо учитывать больше возможностей,
  • Такие вещи, как Equals, трудно создавать в дереве наследования
  • Требуется дополнительная документация
  • Необязательный тип, который является подклассом, может стать изменчивым (ick)

Пункт 17 Эффективной Java более подробно описывает это - независимо от того, что он написан в контексте Java, совет относится и к .NET.

Лично мне хотелось бы, чтобы классы были по умолчанию закрыты в .NET.

Ответ 3

Я нашел это предложение в документации msdn: "Запечатанные классы в основном используются для предотвращения деривации. Поскольку они никогда не могут использоваться в качестве базового класса, некоторые оптимизации во время выполнения могут сделать вызов закрытых членов класса немного быстрее".

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

Ответ 4

Кажется, что официальные рекомендации Microsoft по герметизации развивались после того, как этот вопрос был задан ~ 9 лет назад, и они перешли от опциона -в философии (печать по умолчанию) для отказа (не печать по умолчанию):

X НЕ заклейте классы, не имея для этого веских оснований.

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

Хорошие причины для уплотнения класса включают следующее:

  • Класс - это статический класс. См. "Конструкция статического класса".
  • Класс хранит секретные секреты безопасности в унаследованных защищенных членах.
  • Класс наследует много виртуальных членов и затраты на их герметизацию индивидуально перевешивают преимущества ухода из класса вскрыты.
  • Класс - это атрибут, который требует очень быстрой работы Погляди. Запечатанные атрибуты имеют несколько более высокие уровни производительности чем вскрытые. См. Атрибуты.

X НЕ объявлять защищенные или виртуальные элементы на закрытых типах.

По определению запечатанные типы не могут быть унаследованы. Это значит, что защищенные члены на запечатанных типах не могут быть вызваны, а виртуальные методы с закрытыми типами не могут быть переопределены.

✓ СООТВЕТСТВУЕТ уплотняющие элементы, которые вы переопределите. Проблемы, которые могут возникнуть в результате внедрения виртуальных членов (обсуждаемых в виртуальных членах) применимы и к переопределениям, хотя и в несколько меньшей степени. Уплотнение переопределения защищает вас от этих проблем, начиная с этого точки в иерархии наследования.

В самом деле, если вы найдите основную кодовую базу ASP.Net, вы найдете только около 30 вхождений sealed class, большинство из которых являются атрибутами и тестовыми классами.

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

Ответ 5

Производительность является важным фактором, например, класс string в java является окончательным (< - опечатано), и причина этого - только производительность. Я думаю, что еще один важный момент - избежать описанной здесь проблемы хрупкого базового класса: http://blogs.msdn.com/ericlippert/archive/2004/01/07/virtual-methods-and-brittle-base-classes.aspx

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

Ответ 6

Запечатанный используется для предотвращения "проблемы с хрупким базовым классом". Я нашел хорошую статью в MSDN, которая объясняет это.

Ответ 7

Уплотнение позволяет реализовать некоторые незначительные повышения производительности. Это менее справедливо в мире JIT и ленивой пессимизации, чем в мире, скажем, на С++, но поскольку .NET не так хорош, как пессимизация, поскольку java-компиляторы в основном из-за разных философий дизайна, это по-прежнему полезно. Он сообщает компилятору, что он может напрямую вызывать любые виртуальные методы, а не называть их косвенно через vtable.

Также важно, когда вы хотите "закрытый мир" для таких вещей, как сравнение равенства. Обычно, как только я определяю виртуальный метод, я довольно сильно хожу для определения понятия сравнения равенства, которое действительно реализует идею. С другой стороны, я мог бы определить его для конкретного подкласса класса с помощью виртуального метода. Уплотнение этого класса гарантирует, что равенство действительно выполняется.

Ответ 8

Уплотнение класса упрощает управление одноразовыми ресурсами.