2012-07-03 27 views
8

Tengo una estructura de árbol de categoría/archivo. Ambas categorías y archivos pueden tener padres, por lo que los derivé de una clase base común que tiene una propiedad Parent. Dado que todos los padres, obviamente, siempre serán categorías (los archivos no pueden ser padres), parece tener sentido hacer que la propiedad principal del nodo sea del tipo CategoryNode.¿Es mala forma referirse a un tipo derivado en un tipo base?

¿Es malo que la clase base se refiera a la clase derivada? Si es así, ¿por qué? ¿Cuál es una mejor manera de estructurar esto, si es así?

class Node { 
    public CategoryNode Parent {get; set;} 
} 

class File : Node { 
    ... 
} 

class CategoryNode : Node { 
    ... 
} 
+0

AFAIU, ambos amplían la misma clase base para compartir propiedades, entonces ¿Por qué no usar en una sola clase con referencia recursiva a sí mismo? con propiedades adicionales para distinguirlos. –

+0

sí, eso es malo. Causa dependencia circular. La base no debería saber nada sobre Derived. – Tilak

+0

@Furqan, el nodo Archivo no necesita las cosas adicionales que tiene CategoryNode, como los niños, por lo que no creo que deba derivarse de CategoryNode. – Kelsie

Respuesta

4

Si la propiedad Parent es realmente una propiedad común de todos los descendientes y siempre de tipo CategoryNode, no es un problema. Semánticamente hablando es correcto y técnicamente creo que también es correcto tan pronto como permaneces en la misma biblioteca (para evitar referencias circulares).

Esto puede ser un problema cuando se escribe código como este:

// BAD CODE 
if(myProp is subclassA) 
{ ... 
} 
else if (myProp is syubclassB) 
{ ... 
} 

Este código es malo, porque se pierde la ventaja de la herencia.

Incluso en .Net Framework existen dichos constructos. El primer ejemplo que viene a mi mente es la propiedad XObject.Parent.

XElement hereda XObject y XObject publica una propiedad de tipo XElement. Igual que tu fragmento.

1

La clase base no debería saber quién se deriva de ella.

Si tiene un caso así, probablemente no desee la herencia. Deberías usar alguna forma de acoplamiento.

El archivo y CategoryNode debe contener un miembro Node en su caso.

+0

No puedo estar de acuerdo contigo. ¿Qué pasa si Parent es siempre un CategoryNode? Puede ser un problema en la clase base hay cosas como 'if (myProp es subclassA) {...} else if (myProper es syubclassB) {...}'. Tales cosas están sucias. Pero no la muestra que OP sugiere –

+0

Pero no lo es. acabamos de ver que el padre puede ser File, que de ninguna manera está asociado a CategoryNode. –

+0

OP dijo que 'los archivos no pueden ser uno de los padres' –

1

Otras opciones serán cambiar la jerarquía de clases para convertir el CategoryNode en una clase raíz (a) o cambiar el tipo de propiedad a Node (b).

Ambas posibilidades no son buenas: (a) El archivo tendrá todas las funcionalidades que tiene CategoryNode que no necesita. (b) Ocultará el tipo de objeto (que siempre es CategoryNode). Esto puede seguir a los errores de conversión no válidos en otro lugar en su código. Por ejemplo, si olvida que siempre hay una instancia de CategoryNode.

Teniendo esto en cuenta, creo que el código actual es correcto.

7

Se podría hacer ...

interface IParent { 
    ... 
} 

class Node { 
    public IParent Parent {get; set;} 
} 

class File : Node { 
    ... 
} 

class CategoryNode : Node, IParent { 
    ... 
} 

De esta forma, no es necesario hacer referencia a un objeto derivado de la clase base, además, es más flexibles en lo que realmente puede llegar a ser un padre , en caso de que obtenga tipos de objetos adicionales en un momento posterior. Además, cualquier funcionalidad que sea relevante solo para un padre se puede declarar en esa interfaz.

+0

Tal vez pueda agregar en la interfaz:' IEnumerable ChildNodes'? –

+0

@Steve Esta es una pregunta de diseño. Seguramente eso es posible, pero ya no llamaría a la interfaz 'IParent'. El OP quería referirse a un objeto principal, y no a una (lista de) objeto (s) hijo (s). A mí me parece extraño que algo así se declare como 'IEnumerable Children', y personalmente cambiaría el nombre de la interfaz a algo más apropiado ... si tienes un proyecto grande con muchos ejemplos de ese tipo de estilo de nombre, Estoy en el camino al infierno en mi humilde opinión ... – takrl

+0

tienes razón ... esto puede conducir a la confusión –

Cuestiones relacionadas