.net - una - title en seo
¿Por qué existe la palabra clave ''sellada'' en.Net? (9)
Depende, hay clases que están destinadas a ser simplemente instanciadas (la herencia, si existe, se usa solo para simplificar la implementación), otras clases están destinadas a ser heredadas para proporcionar una implementación específica.
Las clases selladas tienen algunas ventajas:
- no tienen ningún método virtual, por lo que no tienen que preocuparse por métodos de anulación implementados que no sean "seguros para excepciones".
- Si una clase es inmutable, puede preservar y garantizar la inmutabilidad.
De lo contrario, si desea decorar una clase sellada con métodos de "comodidad", use los métodos de extensión (C # 3.0).
Un gran número 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.
¿Hay una buena razón para la existencia de la palabra clave ''sellada''?
Como ejemplo, NotifyCollectionChangedEventArgs en Silverlight está sellado. Quería crear mi propia versión de ObservableCollection que admite AddRange y RemoveRange, pero la versión de Silverlight de NCCEA no proporciona un constructor que admita varios elementos para las propiedades NewItems y OldItems, que ya están definidas como ILists. Por lo general, simplemente extendía la clase con mi propia variante que anulaba las propiedades NewItems y OldItems, pero en este caso no puedo y no veo ninguna razón por la que ese debería ser el caso.
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é es la herencia en realidad. No es solo una forma de alterar la clase, también proporciona polimorfismo. ¿Qué sucede si cambia la semántica de, por ejemplo, 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.
Si bien 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 central.
Aunque de nuevo, tiendo a sentir que el equipo .NET sella demasiadas clases. El sellado a veces puede ser simple pereza por parte del desarrollador porque un diseño de clase adecuado sería demasiado trabajo.
Sin profundizar demasiado, comprenda que Microsoft está a favor de sellar una clase cuando existen posibles problemas de seguridad, mantenimiento o compatibilidad con versiones anteriores que tendrá que tratar aguas abajo. Por ejemplo, System.String
está sellado por razones de seguridad y rendimiento.
En este caso particular, necesitaría preguntarle 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 tendrá que 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, 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 no haber sido virtualizadas, lo que aún te dejaría en el arroyo.
En su escenario específico, iría con métodos de extensión con sus propios nombres únicos. Es todo lo que puedes hacer.
Solo porque algo sea un objeto, no significa que siempre debe estar abierto para que todos extiendan o redefinan su comportamiento.
Una buena analogía sería una puerta y una cerradura. 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, las personas tienden a pecar un poco en el lado más cauteloso y tienen las clases selladas por defecto, a menos que haya un escenario explícito que requiera que se extiendan.
Yo sugeriría que no hay una buena razón para cerrar clases aparte de 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.
Cuando 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 tipos de datos antiguos, pero no estoy convencido de ninguna manera.
Uno de los usos prácticos en los que 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 más frágiles de la clase base http://www.youtube.com/watch?v=xnA3RUJcyY4
Déjame explicar un poco en detalle.
Considere el siguiente escenario donde tenemos una clase padre llamada "DbParent" con un método virtual "Insertar".
clase DbParent {
public virtual void Insert()
{
Console.WriteLine("Parent insert");
}
}
A continuación se muestra una clase infantil simple con su propia implementación "Insertar" que se instala en varios lugares.
class DbChildClass : DbParent
{
public void Insert()
{
Console.WriteLine("Child inserts");
}
}
Ahora, digamos, después de algunos meses de implementación, los desarrolladores de clase primaria sin entender el impacto en las clases secundarias ir y agregar 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");
}
}
Ahora los programas cliente que invocan el método "Agregar" al crear objetos de clase secundarios esperan que se llame a la implementación "Insertar" de la clase "Niño".
DbChildClass o = new DbChildClass();
o.Add();
Console.Read();
Pero, si ejecutas el siguiente código, verás que se llama a la clase padre "Insertar", que NO ES ESPERADA.
Así que iría y marcaría la clase como "Sellada" para evitar tales problemas.
Diseñar clases (o marcos) para que sean extensibles no es trivial, y simplemente la herencia no es el principio único de la programación orientada a objetos.
Tan sealed
existe para permitir que el desarrollador / diseñador exprese y conserve 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 clase de hoja por defecto. Luego, cuando el desarrollador crea intencionalmente una clase no sellada, los obliga a pensar en la extensibilidad.
Ref: Eric Lippert: ¿Por qué se sellan tantas clases de Framework?
Esta respuesta de una pregunta algo relacionada que hice hoy podría ayudar a aclarar los propósitos de sellar una clase:
Me encontré haciendo la misma pregunta hasta que comencé a trabajar en bibliotecas propias reutilizables. Muchas veces terminas con ciertas clases que simplemente no se pueden extender sin requerir secuencias oscuras o arcanas de llamadas del implementador.
Al permitir que se amplíe tu clase, debes preguntar: si un desarrollador extiende mi clase y pasa esta nueva clase a mi biblioteca, ¿puedo trabajar de forma transparente con esta nueva clase? ¿Puedo trabajar correctamente con esta nueva clase? ¿Esta nueva clase realmente se comportará de la misma manera?
He descubierto que la mayoría de las veces las clases selladas en .Net Framework tienen ciertos requisitos bajo el capó de los que usted no es consciente y que, dada la implementación actual, no pueden exponerse de forma segura a subclases.
Substición y composición de Liskov
Ahora sigue ese enlace y sube el voto al autor real.