2009-02-16 17 views
12

Una gran cantidad de clases en .Net Framework están marcadas como 'selladas', lo que le impide heredar esas clases con las suyas propias. Sin duda, esto va en contra de la naturaleza de la orientación a objetos, donde se puede extender y redefinir el comportamiento de los objetos existentes.¿Por qué existe la palabra clave 'sellado' en .Net?

¿Existe una buena razón para la existencia de la palabra clave 'sellado'?

Como ejemplo, NotifyCollectionChangedEventArgs en Silverlight está sellado. Quería crear mi propia versión de ObservableCollection que apoyó AddRange y removeRange, pero la versión de Silverlight de NCCEA no lo hace proporcionar un constructor que apoya varios elementos para los newitems y propiedades OldItems, que ya están definidos como ILists. Normalmente, solo amplía la clase con mi propia variante que anula las propiedades NewItems y OldItems, pero en este caso no puedo y no veo ninguna razón por la cual debería ser el caso.

+5

Es posible que desee leer la publicación del blog de Eric Lippert sobre por qué la mayoría de las cosas en el marco de .NET están selladas: http://blogs.msdn.com/ericlippert/archive/2004/01/22/61803.aspx – gix

+0

porque java tiene el modificador/s de clase 'final' –

Respuesta

21

clases Diseñando (o marcos) para ser extensible no es trivial, y poner simplemente la herencia no es el único principio de la programación orientada a objetos.

Así sealed existe para permitir que el desarrollador/diseñador para expresar y preservar esas intenciones. Sellar una clase también puede hacerles la vida más fácil al reducir la carga de mantenimiento. Le permite al desarrollador original controlar cómo se extiende la clase (o marco), de modo que puedan realizar cambios internos sin preocuparse por romper los cambios en el código de los demás.

Un principio es que los desarrolladores deben sellar cualquier hoja clases por defecto. Luego, cuando el desarrollador crea intencionalmente una clase no sellada, los obliga a pensar en la extensibilidad.


Ref: Eric Lippert - Why Are So Many Of The Framework Classes Sealed?

+0

Creo que estoy leyendo algo mal aquí. Leí que dices que está hecho para preservar las intenciones de los desarrolladores de los marcos ** y ** debemos sellar cualquier clase por defecto para facilitar el desarrollo local. Eso parece contradecir la primera idea, porque si sellas todas las clases estarás causando muchos problemas a cualquiera que use tu marco. O bien, ¿qué deberíamos hacer si pensamos que necesitamos extender una clase sellada? Por lo tanto, tal vez ayude si pudiera dar un buen ejemplo práctico sobre cómo y cuándo debe usarse y por qué es bueno que exista. ¿Podrías por favor? :-) – cregox

+0

@Cawas Realmente solo estoy abogando por proporcionar el punto de extensión de herencia cuando está diseñado y pensado. Idealmente, una base de código más simple le facilitará la vida al reducir los costos de mantenimiento a largo plazo. –

+0

Bueno, en aquel entonces yo estaba tratando de entender, sin ningún trasfondo, exactamente lo mismo que hice con la pregunta. * Por qué 'sellado' incluso existe *. Y tu respuesta no lo hizo por mí. Ahora puedo ver de dónde vienes. Y lo que extrañé está todo en los detalles ... Permítanme proponer una edición. ;-) – cregox

2

La respuesta corta es, porque Microsoft lo dijo. La respuesta más larga es que Microsoft ha proporcionado un mecanismo para extender clases selladas, llamadas métodos de extensión.

En general, es una mala idea ampliar las clases para las cuales no tiene el código fuente. Por ejemplo, no sabe qué método de llamada base hace a los datos internos del objeto. Sí, puedes usar un reflector o lo que sea para resolverlo, pero en general es mucho mejor usar métodos de composición o extensión.

También debe considerar qué herencia realmente es. No es solo una forma de alterar la clase, también proporciona polimorfismo. ¿Qué sucede si cambia la semántica de, digamos, la clase de cadena, y luego pasa su nueva clase de cadena a un objeto que espera que una cadena actúe de una manera específica? sellado básicamente hace cumplir el contrato de que este objeto siempre funcionará de la manera que usted espera.

+0

Pero si tengo una nueva clase SuperString que amplía la cadena, y no se comporta como lo esperan otras clases, entonces seguramente ese es mi problema como el implementador de la clase SuperString. Parece tonto sellar una clase solo porque otro desarrollador * podría * romperla. –

+0

Eso estaría bien si solo estuvieras usando una cadena en tu propio código. Pero las clases como String se utilizan en todo el marco. Microsoft quiere asegurarse de que no cambien por su propio uso. –

1

Aunque estoy de acuerdo en que .NET probablemente sella demasiado, generalmente se trata de proteger la integridad de un ecosistema. Cuando una de sus principales prioridades es mantener estable su marco general/API/tiempo de ejecución, y existen interdependencias algo frágiles entre las clases, puede ser más seguro evitar que las personas anulen ese comportamiento y desestabilicen inadvertidamente la funcionalidad principal.

Aunque de nuevo, tiendo a sentir que el equipo .NET sella muchas clases. El sellado a veces puede ser simple pereza por parte del desarrollador porque un diseño de clase adecuado sería demasiado trabajo.

6

Esta respuesta de una pregunta de alguna manera relacionado Pregunté hoy podría ayudar a aclarar los efectos de sellado de una clase:

me encontré preguntando la misma cuestión hasta que empecé a trabajar en bibliotecas reutilizables de mi propia. Muchos veces terminan con ciertas clases que simplemente no se pueden extender sin que requieren secuencias oscuras o misteriosas de llamadas del implementador.

Al permitir que su clase que se extendió , usted tiene que preguntarse: si un desarrollador extiende mi clase, y pasa esta nueva clase de mi biblioteca, puedo trabajar de forma transparente con esta nueva clase ? ¿Puedo trabajar correctamente con esta nueva clase ? ¿Esta nueva clase realmente es va a comportarse igual?

He encontrado que la mayoría de las veces los clases cerradas en el .Net Framework tienen ciertos bajo el capó requisitos que no son conscientes de, y que dada la actual aplicación no se puede con seguridad expuesto a subclases.

Liskov Substition and Composition

Ahora sigue este link y Upvote el autor real.

2

sin cavar demasiado profundamente, entienden que Microsoft favorece el sellado de una clase cuando hay potenciales de seguridad, capacidad de mantenimiento o de compatibilidad hacia atrás los problemas que tendrá que hacer frente a aguas abajo. Por ejemplo, System.String está sellado por razones de seguridad y rendimiento.

En este caso particular, necesitaría preguntar a un desarrollador de Microsoft por qué eligieron sellar esa clase. Sin embargo, la literatura de orientación arquitectónica que he estado leyendo últimamente tiende a favorecer un enfoque de "sello a menos que sepa que deberá extenderse". Esta literatura tiende a abrazar el uso de métodos de extensión siempre que sea posible. (No estoy diciendo que estoy de acuerdo con eso, solo digo que eso es lo que he estado leyendo últimamente.)

Incluso si la clase no estuviera sellada, las propiedades en cuestión podrían haberse dejado no virtuales, que aún te dejaría en el arroyo aquí.

En su situación específica, iría con los métodos de extensión con sus propios nombres únicos. Es todo lo que puedes hacer.

0

Depende, hay clases que están destinados a ser simplemente una instancia (herencia, si existe, se utiliza sólo para simplificar la implementación), otras clases están destinadas a ser heredado para proporcionar una implementación específica.

clases selladas tienen algunas ventajas:

  • no tienen ningún métodos virtuales, por lo que no tiene que preocuparse acerca de los métodos que no sean "seguros" excepcionalmente implementadas primordiales.
  • Si una clase es inmutable, puede preservar y garantizar la inmutabilidad.

De lo contrario, si desea decorar una clase sellada con métodos de "confort", utilice los métodos de extensión (C# 3.0).

0

El hecho de que algo sea un objeto no significa que siempre deba estar abierto para que todos extiendan o redefinan su comportamiento.

Una buena analogía sería una puerta y un candado. La naturaleza de una puerta es permitir que la gente pase a través de ella, para eso está construida. Sin embargo, la mayoría de las puertas están diseñadas con cerraduras que pueden limitar la capacidad de las personas para atravesarlas. La decisión de si una puerta tiene un candado y si ese candado está bloqueado por defecto se deja al arquitecto de la habitación, según lo que hay en la habitación y quién debe tener acceso a ella, no por el hecho de que sea una puerta.

Por supuesto, puede ser frustrante si la mayoría de las puertas de un edificio en particular están bloqueadas por defecto, especialmente si hay una por la que realmente desea pasar. :-) He estado allí y he hecho la misma pregunta. La respuesta corta es que, a veces, cuando se diseña un marco complejo, la gente tiende a errar un poco en el lado más prudente y tiene las clases selladas por defecto, a menos que haya un escenario explícito que requiera que se extiendan.

1

Sugeriría que no hay una buena razón para sellar clases que no sea para proteger al ignorante, es decir inocente. Ya conoces el viejo dicho, "les he dado suficiente cuerda y se ahorcarán". Deja que se balanceen, digo. Tal vez este es mi fondo C++, pero estoy bastante cómodo sabiendo que tengo el poder de rellenar las cosas por completo si no soy diligente.

Tiendo a programar por interfaz. Las interfaces son, por supuesto, públicas y cualquiera es libre de proporcionar su propia implementación que cumpla con el contrato expresado por la interfaz. Mis clases concretas que implementan estas interfaces tienden a ser una preocupación privada y están marcadas como internas y/o privadas. No creo que deba sellar esas clases.

Donde la reutilización de código es deseable, evito la reutilización a través de la herencia, lo que favorece la composición y otras técnicas.

El sellado también puede ser válido en tipos que se consideran simples tipos de datos antiguos, pero no estoy convencido de este modo.

0

Uno de los usos prácticos donde he encontrado que la palabra clave sellada es útil es evitar "Problemas de clase frágiles". Aquí hay un video que muestra uno de los problemas de la clase base frágil http://www.youtube.com/watch?v=xnA3RUJcyY4

Déjenme explicarles un poco en detalle.

Considere el siguiente escenario donde tenemos una clase principal denominada "DbParent" con un método virtual "Insertar".

DbParent clase {

public virtual void Insert() 
    { 
     Console.WriteLine("Parent insert"); 
    } 

}

A continuación se muestra una clase simple hijo con su propia aplicación “Insertar”, que se instala a través de varias ubicaciones.

class DbChildClass : DbParent 
    { 
    public void Insert() 
    { 
     Console.WriteLine("Child inserts"); 
    } 

}

Ahora digamos que después de algunos meses de los desarrolladores de la clase padre de despliegue sin entender el impacto en las clases hijas van y añadir un nuevo método “Agregar”. Este método "Agregar" llama internamente al método "Insertar" (a continuación se muestra el fragmento de código para el mismo).

class DbParent 
    { 
    public void Add() // Adds method with out consulting 
    { 
    this.Insert(); 
    } 

    public virtual void Insert() 
    { 
     Console.WriteLine("Parent insert"); 
    } 
    } 

programas cliente ahora que invocan el método “Agregar” mediante la creación de objetos de la clase hijo esperan que el “Niño” clase “Insertar” aplicación debe ser llamado.

DbChildClass o = new DbChildClass(); 
    o.Add(); 
    Console.Read(); 

Pero whoaaaa, si se ejecuta el código de abajo verá la clase padre “Insertar” se llama que no se espera.

Así que iría y marcaría la clase como "Sellada" para evitar estos problemas.

Cuestiones relacionadas