Зачем запечатывать класс?
Я хотел бы услышать, какова мотивация большинства запечатанных классов в .Net framework. В чем преимущество герметизации класса? Я не могу понять, как не разрешать наследование может быть полезным и, скорее всего, не единственным, кто борется с этими классами.
Итак, почему фреймворк спроектирован таким образом, и не будет ли это неразрывным изменением, чтобы вскрыть все? Должна быть другая причина, но просто быть злым?
10 ответов:
- иногда классы слишком ценны и не предназначены для наследования.
- Runtime / Reflection может делать предположения наследования о запечатанных классах при поиске типов. Отличный пример этого - атрибуты рекомендуется запечатать для скорости выполнения поиска. тип.GetCustomAttributes(typeof (MyAttribute)) будет работать значительно быстрее, если MyAttribute запечатан.
статья MSDN для этой темы ограничение расширения Классы Герметизации.
классы должны быть либо предназначены для наследования, либо запрещать его. Существует стоимость проектирования для наследования:
- Он может закрепить вашу реализацию (Вы должны объявить, какие методы будут вызывать какие другие методы, в случае, если пользователь переопределяет один, но не другой)
- Это показывает вашу реализацию, а не только эффекты
- Это означает, что вы должны думать больше возможностей при проектировании
- такие вещи, как равных трудно спроектировать в дереве наследования
- требуется больше документации
- неизменяемый тип, который является подклассом, может стать изменяемым (ick)
пункт 17 эффективной Java переходит к более подробной информации об этом-независимо от того, что он написан в контексте Java, совет применяется и к .NET.
лично я хотел бы, чтобы классы были запечатаны по умолчанию в. NET.
Кажется,официальные рекомендации Microsoft по герметизации эволюционировали с тех пор, как этот вопрос был задан ~9 лет назад, и они перешли от философии выбора (печать по умолчанию) к отказу (не запечатывать по умолчанию):
X НЕ классы печати без веской причины для этого.
Запечатывание класса, потому что вы не можете придумать сценарий расширяемости это не очень хорошая причина. Пользователи фреймворка любят наследовать от классы для различные неочевидные причины, такие как добавление удобных членов. Видеть Незапечатанные классы для примеров неочевидных причин, по которым пользователи хотят наследовать от типа.
веские причины для герметизации класса включают следующее:
- класс является статическим классом. См. Статический Дизайн Класса.
- класс хранит конфиденциальные секреты в наследуемых защищенных членах.
- класс наследует много виртуальных членов и стоимость их герметизации индивидуально перевешивает преимущества выхода из класса незапечатанный.
- класс является атрибутом, который требует очень быстрого выполнения посмотреть вверх. Запечатанные атрибуты имеют несколько более высокие уровни производительности чем незапечатанные. Ознакомиться С Атрибутами.
X НЕ объявить защищенные или виртуальные члены на запечатанных типах.
по определению, запечатанные типы не могут быть унаследованы от. Это означает, что защищенный члены на запечатанных типах не могут быть вызваны, а виртуальные методы на запечатанных типах не могут быть переопределены.
рекомендуется уплотнительные элементы, которые можно переопределить. Проблемы, которые могут возникнуть в результате введения виртуальных членов (обсуждаются в разделе Виртуальные члены) применяется для переопределения, хотя и в несколько меньшей степени. Запечатывание переопределения защищает вас от этих проблем, начиная с этого точка в иерархии наследования.
в самом деле, если вы поиск ASP.Net основная кодовая база вы найдете только около 30 вхождений
sealed class, большинство из которых являются атрибутами и тестовых классов.Я думаю, что сохранение неизменности является хорошим аргументом в пользу уплотнения.
Я нашел это предложение в документации msdn: "запечатанные классы в основном используются для предотвращения деривации. Поскольку они никогда не могут использоваться в качестве базового класса, некоторые оптимизации времени выполнения могут сделать вызов запечатанных членов класса немного быстрее."
Я не знаю, является ли производительность единственным преимуществом закрытых классов, и лично я также хотел бы знать любые другие причины ...
производительность является важным фактором например, класс string в java является окончательным (http://blogs.msdn.com/ericlippert/archive/2004/01/07/virtual-methods-and-brittle-base-classes.aspx
Если вы предоставляете фреймворк, это важно для поддержки устаревших проектов и для обновления вашего фреймворка, чтобы избежать проблема хрупкого базового класса
Sealed используется для предотвращения "хрупкой проблемы базового класса". Я нашел хорошая статья в MSDN это объясняет.
Запечатывание позволяет вам осуществить некоторые небольшие увеличения представления. Это менее верно в мире JITs и ленивой пессимизации, чем в мире, скажем, C++, но поскольку .NET не так хорош, как пессимизация, поскольку компиляторы java в основном из-за разных философий дизайна, это все еще полезно. Он сообщает компилятору, что он может напрямую вызывать любые виртуальные методы, а не вызывать их косвенно через vtable.
Это также важно, когда вы хотите "закрытый мир" для такие вещи, как сравнение равенства. Обычно, как только я определяю виртуальный метод, я в значительной степени заточен для определения понятия сравнения равенства, которое действительно реализует эту идею. С другой стороны, я мог бы определить его для конкретного подкласса класса с виртуальным методом. Запечатывание этого класса гарантирует, что равенство действительно выполняется.
чтобы определить, следует ли запечатать класс, метод или свойство, обычно следует учитывать следующие два момента:
•потенциальные преимущества, которые могут получить производные классы, могут быть получены благодаря возможности настройки вашего класса.
•возможность того, что производные классы могут изменить ваши классы таким образом, что они больше не будут работать правильно или как ожидалось.
еще одно соображение заключается в том, что запечатанные классы могут быть стаба в модульных тестах. От документация Microsoft:
запечатанные классы или статические методы не могут быть заглушены, поскольку типы заглушек зависят от отправки виртуального метода. В таких случаях используйте типы прокладок, описанные в разделе использование прокладок, чтобы изолировать приложение от других сборок для модульного тестирования
Comments