2008-11-06 13 views
84

Me gustaría saber cuál es la motivación detrás del grueso de las clases selladas en .Net Framework. ¿Cuál es el beneficio de sellar una clase? No puedo entender cómo no permitir que la herencia sea útil y, probablemente, no la única que combate estas clases.¿Por qué sellar una clase?

Entonces, ¿por qué el marco está diseñado de esta manera y no sería un cambio inquebrantable para destrabar todo? Debe haber otra razón, pero solo ser malvado?

+2

Yo diría [no * nunca * selle una clase a menos que * sepa * tendrá problemas de soporte con sus clientes.] (Http://programmers.stackexchange.com/a/210481/4261) – cregox

+1

Posible duplicado de [¿Por qué hay una opción para una clase en OOP marcada para nunca heredar de ancestral?] (Http://stackoverflow.com/questions/12588158/why-there-is-an-option-for-a -class-in-oop-be-marked-to-never-inherit-from-ancest/21116956) – Doval

Respuesta

37
  • A veces las clases son demasiado valiosas y no están diseñadas para ser heredadas.
  • Runtime/Reflection puede hacer suposiciones de herencia sobre clases selladas al buscar tipos. Un gran ejemplo de esto es: se recomienda que los atributos estén sellados para la velocidad de tiempo de ejecución de búsqueda. type.GetCustomAttributes (typeof (MyAttribute)) funcionará significativamente más rápido si MyAttribute está sellado.

El artículo de MSDN para este tema es Limiting Extensibility by Sealing Classes.

+3

Me alegra ver que dicen claramente "usar con precaución" ahora ... aunque desearían que practicaran lo que predican. – mmiika

+11

Eso me parece un mal consejo :( –

+0

No tengo una opinión, no es mi consejo. C# te da el control - que está bien. Nunca me he encontrado con un problema con las clases selladas (es decir, tener el Necesito derivar de uno). Si lo hiciera, me limitaría a envolver la clase sellada en su lugar. – CVertex

3

Encontré esta frase en la documentación de msdn: "Las clases selladas se usan principalmente para evitar la derivación. Debido a que nunca se pueden usar como clase base, algunas optimizaciones en tiempo de ejecución pueden hacer que llamar a miembros de la clase sea un poco más rápido".

No sé si el rendimiento es la única ventaja de las clases selladas y personalmente también me gustaría saber cualquier otra razón ...

+3

Sería interesante ver de qué tipo de beneficio para el rendimiento están hablando ... – mmiika

89

Las clases deben ser bien diseñados para la herencia o prohibirla. Hay un costo para el diseño de la herencia:

  • Se puede precisar su aplicación (usted tiene que declarar qué métodos van a llamar a que otros métodos, en caso de que un usuario anula uno pero no el otro)
  • revela que su aplicación no sólo los efectos
  • que significa que tiene que pensar en más posibilidades en el diseño de
  • cosas como iguales son difíciles de diseñar en un árbol de herencia
  • que requiere más documentación
  • Un tipo inmutable que es una subclase puede llegar a ser mutable (ick)

artículo 17 de Effective Java entra en más detalles sobre esto - sin importar el hecho de que está escrito en el contexto de Java, el consejo se aplica a .NET también.

Personalmente deseo que las clases estén selladas por defecto en .NET.

+23

Hmm .. si extiende una clase, ¿no es su problema si la rompe? – mmiika

+20

¿Qué sucede si un cambio en la implementación del que no tiene control en la clase base lo rompe? ¿De quién es la culpa? La herencia introduce fragilidad, básicamente. Favorecer la composición sobre la herencia promueve la solidez, IMO. –

+2

Es cierto. De acuerdo, tiene sentido si proporciona algunos medios (quizás una interfaz separada) para escribir su propia implementación con fines de comprobación. Acabo de pasar demasiadas horas escribiendo decoradores en estas clases :) – mmiika

2

El rendimiento es un factor importante, por ejemplo, la clase de cadena en java es definitiva (< - sellado) y la razón de esto es solo el rendimiento. Creo que otro punto importante es evitar el problema de la clase base frágil descrito en detalle aquí: http://blogs.msdn.com/ericlippert/archive/2004/01/07/virtual-methods-and-brittle-base-classes.aspx

Si proporciona un marco que es importante para los proyectos de mantenimiento de legado y actualizar su marco para evitar el problema de la clase base frágil

+0

El motivo por el que String in java es definitivo no es el rendimiento, sino la seguridad. – CesarB

+0

@CesarB: Sí, pero también, String no es una clase Java normal. Es la única clase (creo) en Java que admite la sobrecarga del operador (para más información, consulte [aquí] (http://stackoverflow.com/a/194889), sección: "Incluso C y Java tienen una sobrecarga del operador (codificada) "), que no es posible en una clase normal. Debido a esto, la clase 'String' podría no ser posible para la subclase, incluso si no fuera final. – wchargin

0

El sellado le permite obtener algunas ganancias de rendimiento menores. Esto es menos cierto en el mundo de los JIT y la pesimista perezosa que en el mundo de, digamos C++, pero desde entonces.NET no es tan bueno como la pesimismo, ya que los compiladores de Java son en su mayoría debido a filosofías de diseño diferentes que todavía es útil. Le dice al compilador que puede llamar directamente a cualquier método virtual en lugar de llamarlos indirectamente a través del vtable.

También es importante cuando quiere un "mundo cerrado" para cosas como la comparación de igualdad. Normalmente, una vez que defino un método virtual, casi me manchan por definir una noción de comparación de igualdad que realmente implemente la idea. Por otro lado, podría definirlo para una subclase particular de la clase con el método virtual. Sellar esa clase asegura que la igualdad realmente se mantenga.

1

Sellado se utiliza para evitar el "problema de clase de base quebradiza". Encontré un good article en MSDN que lo explica.

0

Sellar una clase facilita la gestión de los recursos desechables.

4

Parece que el official Microsoft guidelines on sealing han evolucionado desde esta pregunta se hizo ~ hace 9 años, y se pasa de una filosofía de opt-in (sellado por defecto) para darse de baja (no selle de manera predeterminada):

X DO NOT selle las clases sin tener una buena razón para hacerlo.

Sellar una clase porque no se puede pensar en un escenario de extensibilidad no es una buena razón. Los usuarios de Framework desean heredar de las clases para varias razones no obvias, como agregar miembros de conveniencia. Consulte Clases sin sellar para ver ejemplos de razones no obvias por las que los usuarios desean heredar de un tipo.

Buenas razones para sellar una clase incluyen los siguientes:

  • La clase es una clase estática. Vea diseño de clase estática.
  • La clase almacena secretos sensibles a la seguridad en miembros protegidos heredados.
  • La clase hereda muchos miembros virtuales y el costo de sellarlos individualmente superaría los beneficios de dejar la clase sin sellar.
  • La clase es un atributo que requiere un tiempo de ejecución muy rápido búsqueda. Los atributos sellados tienen niveles de rendimiento ligeramente más altos que los no sellados. Ver atributos.

X DO NOT declarar miembros protegidos o virtuales en tipos sellados.

Por definición, no se pueden heredar los tipos sellados. Esto significa que los miembros protegidos en tipos sellados no se pueden llamar, y los métodos virtuales en tipos sellados no se pueden anular.

✓ CONSIDERA miembros de sellado que anula. Los problemas que pueden surgir de la introducción de miembros virtuales (discutidos en Miembros virtuales) también se aplican a las modificaciones, aunque en menor grado. Sellar una anulación protege estos problemas a partir de ese punto en la jerarquía de herencia.

De hecho, si search the ASP.Net Core codebase, se encuentra solamente cerca de 30 apariciones de sealed class, la mayoría de los cuales son atributos y clases de prueba.

Creo que la conservación de la inmutabilidad es un buen argumento a favor del sellado.

0

Para determinar si se debe sellar una clase, método o propiedad, se debe considerar generalmente los dos puntos siguientes:

• Los beneficios potenciales que las clases derivadas pueden obtener a través de la posibilidad de personalizar su clase.

• El potencial de que las clases derivadas puedan modificar sus clases de tal manera que ya no funcionarían correctamente o como se esperaba.

Cuestiones relacionadas