Pregunta

Realmente no lo entiendo.

Si la clase base es abstracta y sólo destinado a ser utilizado para proporcionar una funcionalidad común a las subclases públicas definidas en la asamblea, ¿por qué no se declare interna?

No quiero la clase abstracta que sea visible para el código fuera de la asamblea. No quiero código externo que saber al respecto.

¿Fue útil?

Solución

heredando de una clase, se expone la funcionalidad de la clase base a través de su hijo.

Desde la clase hijo tiene una mayor visibilidad a su dominante, se estaría exponiendo a los miembros que de otro modo estarían protegidos.

No se puede violar el nivel de protección de la clase padre mediante la implementación de un niño con una mayor visibilidad.

Si la clase base sirve realmente para ser utilizado por las clases hijas públicas, entonces usted necesita para hacer que el público los padres también.

La otra opción es mantener su "padre" interno, que sea no abstracta, y lo utilizan para componer sus clases hijas, y el uso de una interfaz a clases de fuerza para 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(); }
}

Otros consejos

ACTUALIZACIÓN: Esta cuestión fue el tema de mi blog el 13 de noviembre de 2012 . Verlo por otras de las ideas sobre este tema. Gracias por la gran pregunta!


Tienes razón; que no tiene por qué ser así. Otros lenguajes orientados a objetos permiten "herencia privada", por lo que el hecho de que hereda D de B sólo pueden ser aprovechadas por el código que tiene la capacidad de ver B.

Esta fue una decisión de diseño de los diseñadores originales de C #. Por desgracia estoy lejos de mi escritorio en este momento - Me estoy tomando un par de días de descanso para el fin de semana largo - por lo que no tengo las notas de diseño del lenguaje a partir de 1999 frente a mí. Si pienso en ello cuando vuelva voy a navegar por ellos y ver si hay una justificación para esta decisión.

Mi opinión personal es que la herencia debe ser usado para representar "es una especie de" relaciones; es decir, la herencia debe representan la semántica del dominio que está siendo modelado en el idioma . Trato de Evitará situaciones en que se utiliza la herencia como un mecanismo de reparto de código . Como otros han mencionado, es probablemente el mejor preferir composición a la herencia, si lo que quiere representar es "esta clase de acciones mecanismos de aplicación con otras clases".

Creo que lo más cerca que puede hacer es prevenir la creación de otros conjuntos de la clase abstracta por lo que es del constructor interna, para citar MSDN :

  

Un constructor interno impide la clase abstracta de ser utilizado como la clase base de tipos que no están en el mismo conjunto que la clase abstracta.

A continuación, puede intentar añadir un EditorBrowsableAttribute a la clase para tratar de ocultarlo de Intellisense (aunque, he tenido resultados mixtos que lo utilizan para ser honesto) o poner la clase base en un espacio de nombres anidados, como MyLibrary.Internals para separarlo del resto de sus clases.

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

Inheritance debe servir como un mecanismo de categorización, mientras que a menudo se utiliza para la reutilización de código.

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

class MyClass : MyReusedClass { }

Sin embargo, con el fin de componer, tenemos que hacerlo por nosotros mismos:

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á composición al mismo nivel de usabilidad como herencia.

Hay investigaciones sobre rasgos en C # (pdf) , y sería algo parecido a esto:

class MyClass {
  uses { MyTrait; }
}

A pesar de que me gustaría ver otro modelo (el de Perl 6 papeles).

ACTUALIZACIÓN:

Como nota al margen, el lenguaje tiene Oxygene un característica que le permite delegar todos los miembros de una interfaz a una propiedad de miembro que implementa esa interfaz:

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

A continuación, todos los miembros de la interfaz de IReusable estará expuesto a través MyClass y van a toda delegado a la propiedad Reused. Hay algunos problemas con este enfoque, sin embargo.

Otra actualización:

He comenzado a implementar este concepto composición automática en C #: echar un vistazo a NRoles .

Creo que esto violaría la principio de sustitución de liskov .

En casos como este, he utilizado las clases internas y prefieren composición sobre la herencia. ¿Hay algo en su diseño que prohíbe que contiene toda esta funcionalidad en su clase interna, y luego tienen sus clases públicas contienen una instancia de esta clase interna?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top