una qué que programacion polimorfismo objeto metodos interfaces herencia ejemplos clases clase abstracta c# inheritance internal

c# - qué - que es una clase en programacion



¿Por qué mi clase pública no puede extender una clase interna? (5)

Realmente no lo entiendo.

Si la clase base es abstracta y solo pretende ser utilizada para proporcionar una funcionalidad común a las subclases públicas definidas en el ensamblado, ¿por qué no debería declararse interna?

No quiero que la clase abstracta sea visible para codificar fuera del ensamblaje. No quiero que el código externo lo sepa.


ACTUALIZACIÓN: Esta pregunta fue el tema de mi blog el 13 de noviembre de 2012 . Véalo para más ideas sobre este tema. Gracias por la gran pregunta!

Tienes razón; no tiene por qué ser así. Otros lenguajes OO permiten "herencia privada", por lo que el hecho de que D hereda de B solo puede aprovecharse mediante un código que tenga la capacidad de ver B.

Esta fue una decisión de diseño de los diseñadores originales de C #. Desafortunadamente, ahora mismo estoy lejos de mi escritorio, me tomaré un par de días libres durante el fin de semana largo, así que no tengo las notas de diseño de idiomas de 1999 frente a mí. Si lo pienso cuando regrese lo buscaré y veré si hay una justificación para esta decisión.

Mi opinión personal es que la herencia debe usarse para representar "es un tipo de" relación; es decir, la herencia debe representar la semántica del dominio modelado en el lenguaje . Intento evitar situaciones en las que la herencia se usa como mecanismo de intercambio de código . Como otros han mencionado, probablemente sea mejor preferir la composición a la herencia si lo que quiere representar es "esta clase comparte mecanismos de implementación con otras clases".


Al heredar de una clase, expones la funcionalidad de la clase base a través de tu hijo.

Dado que la clase para niños tiene una mayor visibilidad que su padre, expondría a los miembros que de otro modo estarían protegidos.

No se puede violar el nivel de protección de la clase principal implementando un niño con mayor visibilidad.

Si la clase base está destinada a ser utilizada por clases públicas para niños, entonces también debe hacer que el padre sea público.

La otra opción es mantener su "padre" interno, hacerlo no abstracto y usarlo para componer sus clases secundarias, y usar una interfaz para forzar a las clases a implementar la funcionalidad:

public interface ISomething { void HelloWorld(); } internal class OldParent : ISomething { public void HelloWorld(){ Console.WriteLine("Hello World!"); } } public class OldChild : ISomething { OldParent _oldParent = new OldParent(); public void HelloWorld() { _oldParent.HelloWorld(); } }


Creo que estás mezclando preocupaciones aquí, y C # tiene la culpa, en realidad (y Java antes).

La herencia debe servir como un mecanismo de categorización, mientras que a menudo se usa para la reutilización del código.

Para la reutilización de código, siempre se ha sabido que la composición supera a la herencia. El problema con C # es que nos da una manera tan fácil de heredar:

class MyClass : MyReusedClass { }

Pero para componer, tenemos que hacerlo solos:

class MyClass { MyReusedClass _reused; // need to expose all the methods from MyReusedClass and delegate to _reused }

Lo que falta es un constructo como un rasgo (pdf) , que traerá la composición al mismo nivel de usabilidad que la herencia.

Hay una investigación sobre los rasgos en C # (pdf) , y se vería más o menos así:

class MyClass { uses { MyTrait; } }

Aunque me gustaría ver otro modelo (el de los roles de Perl 6).

ACTUALIZAR:

Como nota al margen, el lenguaje Oxygene tiene una función que le permite delegar todos los miembros de una interfaz a una propiedad miembro que implementa esa interfaz:

type MyClass = class(IReusable) private property Reused : IReusable := new MyReusedClass(); readonly; implements public IReusable; end;

Aquí, todos los miembros de la interfaz de IReusable se IReusable a través de MyClass y todos ellos delegarán en la propiedad Reused . Sin embargo, hay algunos problems con este enfoque.

OTRA ACTUALIZACIÓN:

Comencé a implementar este concepto de composición automática en C #: eche un vistazo a NRoles .


Creo que esto violaría el Principio de Sustitución de Liskov .

En casos como este, he usado clases internas y prefiero la composición a la herencia. ¿Hay algo acerca de su diseño que prohíba contener toda esa funcionalidad en su clase interna, y luego tener sus clases públicas contienen una instancia de esta clase interna?


Creo que lo más cercano que puede hacer es evitar que otros ensambles creen la clase abstracta haciendo que su constructor sea interno, para citar desde MSDN :

Un constructor interno evita que la clase abstracta se use como clase base de tipos que no están en el mismo ensamblaje que la clase abstracta.

Luego puede intentar agregar un EditorBrowsableAttribute a la clase para tratar de ocultarlo de Intellisense (aunque he tenido resultados mixtos al usarlo para ser honesto) o poner la clase base en un espacio de nombres anidado, como MyLibrary.Internals para separarlo del resto de tus clases.