multiple method inherits inherited herencia c# inheritance

method - ¿Tiene C#la noción de herencia privada y protegida?



inherits (10)

¿Tiene C # la noción de herencia privada / protegida, y si no, por qué?

C ++

class Foo : private Bar { public: ... };

DO#

public abstract NServlet class : private System.Web.UI.Page { // error "type expected" }

Estoy implementando un concepto de "servlet like" en una página .aspx y no quiero que la clase concreta tenga la capacidad de ver las partes internas de la base System.Web.UI.Page.


No, no. ¿Cuál sería el beneficio de permitir este tipo de restricción?

La herencia privada y protegida es buena para la encapsulación (ocultación de información). La herencia protegida * se admite en C ++, aunque no está en Java. Aquí hay un ejemplo de mi proyecto en el que sería útil.

Hay una clase base en el marco de terceros **. Tiene docenas de ajustes más propiedades y métodos para manipularlos. La clase base no realiza muchas comprobaciones cuando se asignan configuraciones individuales, pero generará una excepción más adelante si encuentra una combinación inaceptable.

Estoy haciendo una clase infantil con métodos para asignar estos ajustes (por ejemplo, asignar configuraciones cuidadosamente elaboradas a partir de un archivo). Sería bueno negar el resto del código (fuera de mi clase infantil) la capacidad de manipular configuraciones individuales y estropearlas.

Dicho esto, creo que en C ++ (que, una vez más, admite la herencia privada y protegida), es posible convertir la clase secundaria en principal y obtener acceso a los miembros públicos de los padres. (Véase también la publicación de Chris Karcher ). Sin embargo, la herencia protegida mejora la ocultación de la información. Si los miembros de una clase B1 deben estar realmente ocultos dentro de otras clases C1 y C2, se pueden organizar haciendo una variable protegida de una clase B1 dentro de C1 y C2. La instancia protegida de B1 estará disponible para los niños de C1 y C2. Por supuesto, este enfoque por sí mismo no proporciona polimorfismo entre C1 y C2. Pero se puede agregar polimorfismo (si se desea) heredando C1 y C2 de una interfaz común I1.

*** Para abreviar, usará "protegido" en lugar de "privado y protegido".

** National Instruments Measurement Studio en mi caso.

  • Mella

@bdukes: tenga en cuenta que no está realmente ocultando al miembro. P.ej:

class Base { public void F() {} } class Derived : Base { new private void F() {} } Base o = new Derived(); o.F(); // works

EDITAR: Pero esto logra lo mismo que la herencia privada en C ++, que es lo que quería el consultante :)


C # solo permite la herencia pública. C ++ permitió los tres tipos. La herencia pública implicaba un tipo de relación "IS-A" y la herencia privada implicaba un tipo de relación "Is-Implemented-In-Terms-Of". Debido a que las capas (o la composición) lograron esto de una manera posiblemente más simple, la herencia privada solo se usaba cuando los miembros protegidos o las funciones virtuales lo requerían absolutamente, según Scott Meyers en Effective C ++, Item 42.

Supongo que los autores de C # no consideraron que este método adicional de implementar una clase en términos de otro fuera necesario.


No, herencia pública solamente.


No, no. ¿Cuál sería el beneficio de permitir este tipo de restricción?


Probablemente desee una clase ServletContainer que se conecte con una implementación de NServlet. En mi libro, no permitir la herencia privada / protegida no es realmente un gran problema y mantiene el lenguaje menos confuso: con LINQ, etc., ya tenemos suficientes cosas para recordar.


Puede ocultar que las API heredadas no sean públicamente visibles al declarar ese mismo miembro en su clase como privado y usar la nueva palabra clave. Consulte Ocultar a través de herencia de MSDN.


Sé que esta es una vieja pregunta, pero me he encontrado con este problema varias veces al escribir C #, y quiero saber ... ¿por qué no usar una interfaz?

Cuando crea su subclase de la clase del marco de terceros, también pida que implemente una interfaz pública. Luego defina esa interfaz para incluir solo los métodos a los que desea que acceda el cliente. Luego, cuando el cliente solicite una instancia de esa clase, en su lugar, déles una instancia de esa interfaz.

Esa parece ser la forma aceptada por C # de hacer este tipo de cosas.

La primera vez que hice esto fue cuando me di cuenta de que la biblioteca estándar de C # no tenía una variante de solo lectura de un diccionario. Quería proporcionar acceso a un diccionario, pero no quería darle al cliente la posibilidad de cambiar elementos en el diccionario. Así que definí una "clase DictionaryEx <K, V, IV>: Diccionario <K, V>, IReadOnlyDictionary <K, IV> donde V: IV" donde K es el tipo de clave, V es el tipo de valor real, y IV es una interfaz para el tipo V que evita cambios. La implementación de DictionaryEx fue en su mayoría simple; la única parte difícil fue crear una clase ReadOnlyEnumerator, pero incluso eso no llevó mucho tiempo.

El único inconveniente que puedo ver con este enfoque es si el cliente intenta lanzar dinámicamente su interfaz pública a la subclase relacionada. Para detener esto, haz que tu clase sea interna. Si tu cliente lanza tu interfaz pública a la clase base original, creo que sería muy claro para ellos que se están quitando la vida en sus propias manos. :-)


Si desea que la clase NServlet no sepa nada sobre la página, debe considerar el uso del patrón Adapter. Escriba una página que albergará una instancia de la clase NServlet. Dependiendo de lo que esté haciendo exactamente, podría escribir una gran variedad de clases que solo conozcan NServlet de la clase base sin tener que contaminar su API con los miembros de la página asp.net.


Primera solución:

los actos internos protegidos como públicos en la misma asamblea y protegidos en otras asambleas.

Debería cambiar el modificador de acceso de cada miembro de la clase que no debe exponerse a través de la herencia.

Sin embargo, es un poco restrictivo que esta solución requiera y obligue a la clase a ser heredada para ser utilizada por otro ensamblado. Por lo tanto, la elección de ser usado solo por herencia o no es tomado por el padre desconocido ... normalmente los niños conocen más la arquitectura ...

No es una solución perfecta, pero podría ser una mejor alternativa que agregar una interfaz para ocultar métodos y aún así dejar la posibilidad de utilizar los métodos principales para que se oculte a través de la clase secundaria porque es posible que no pueda forzar fácilmente el uso de la interfaz.

Problema:

Los modificadores de acceso privado y protegido no se pueden usar para los métodos que están implementando interfaces . Eso significa que la solución interna protegida no se puede usar para los métodos implementados por la interfaz. Esta es una gran restricción.

Solución final:

Me volví a la solución de interfaz para ocultar los métodos .

El problema con esto era poder forzar el uso de la interfaz para que los miembros que se esconden SIEMPRE estén ocultos y luego eviten definitivamente los errores.

Para forzar el uso solo de la interfaz , simplemente haga que los constructores estén protegidos y agregue un método estático para la construcción (lo llamé Nuevo). Este nuevo método estático es de hecho una función de fábrica y devuelve la interfaz . ¡Entonces el resto del código tiene que usar solo la interfaz!