2009-04-28 14 views
7

¿Cuáles son las situaciones y los beneficios asociados de usar genéricos sobre herencia y viceversa, y cómo deberían combinarse mejor?¿Cuándo es apropiado usar genéricos versus herencia?

Gracias por la respuesta chicos.

voy a tratar de indicar el motivo de esta pregunta lo mejor que pueda: tengo una clase como se muestra a continuación:

class InformationReturn<T> where T : Info 
{ 
    InformationReturn(Employee employee, List<T>) { ... } 
} 

Ahora supongamos que tengo un repositorio que toma un argumento InformationReturn, eso tiene que crear diferentes campos en un DB dependiendo del tipo de objeto de información T es. ¿Es mejor crear repositorios diferentes para el tipo T? un repositorio que utiliza la reflexión para determinar el tipo; o hay una forma mejor de usar capacidades de herencia sobre/con genéricos?

Nota: otro código de cliente debe operar de manera diferente según el tipo de T también.

Respuesta

4

Son muy diferentes ideas en conjunto. Los genéricos le permiten declarar la funcionalidad "específica" común (a riesgo de sonar oxímorónico) de una manera general. Un List<int> no funciona de manera diferente a un List<string>, aparte del tipo de datos que se guardan dentro.

Mientras la herencia se podría utilizar para hacer la misma cosa, que podría crear una clase List, a continuación, una y una clase IntListStringList que heredan de ella. Fácilmente podría hacer que estas dos clases funcionen de forma completamente diferente, o tener una funcionalidad de oferta no disponible en la otra.

Editar

Después de revisar la edición a la pregunta, la respuesta sortof es "depende". Puede hacer argumentos para ambos lados, y, de hecho, LINQ to SQL y Entity Framework son una combinación de inspección reflectiva usando genéricos y clases de entidad fuertemente tipadas y otras clases de repositorio. Ciertamente puede adoptar el enfoque que está mirando, solo sepa que, en general, un problema que puede resolverse con reflexión o con otra cosa PROBABLEMENTE será más rápido cuando sea resuelto por "otra cosa". Todo se reduce a la cantidad de compromiso que desee entre rendimiento, facilidad de mantenimiento, legibilidad y confiabilidad.

+0

Esta respuesta me ayudó a señalar que debo usar genéricos cuando no hay diferencia en el comportamiento y la herencia de lo contrario, gracias. He modificado la pregunta para aclarar mis motivaciones. – Laz

10

Los genéricos y la herencia son dos cosas separadas. La herencia es un concepto de OOP y los genéricos son una característica de CLR que le permite especificar parámetros de tipo en tiempo de compilación para los tipos que los exponen.

La herencia y los genéricos en realidad funcionan bastante bien juntos.

Herencia:

Herencia me permite crear un tipo:

class Pen { } 

y luego crear otro tipo que se extiende Pen:

class FountainPen : Pen { } 

Esto es útil porque puedo reutilizar todo el estado y el comportamiento de la clase base y exponer cualquier comportamiento o estado nuevo en FountainPen. La herencia me permite crear rápidamente una versión más específica de un tipo existente.

Genéricos:

genéricos son una característica CLR que me deja crear un tipo como éste:

class Foo<T> 
{ 
    public T Bar { get; set; } 
} 

Ahora cuando uso Foo<T> puedo especificar cuál es el tipo de T estará proporcionando un argumento de tipo genérico:

Foo<int> foo = new Foo<int>(); 

Ahora, ya que he especificado que T será un int para el objeto que acabo de crear, el tipo de Foo.Bar también será int ya que fue declarado del tipo T.

+3

¿Pero cuándo se debe usar cada uno? –

+1

Pedazo de pedantería: proporciona un tipo genérico * argumento *, es decir, T es el parámetro de tipo, int es el argumento de tipo. Dejaré que decidas si vale la pena editarlo o no :) –

+0

¡Reparado! Gracias por señalar eso, la pedantería nunca es inoportuna, Dios sabe que reparto bastante de ella :) –

3

La herencia es mucho más acerca de "is-a" (la rana es un animal) donde los genéricos se trata de crear contenedores que actúan sobre datos tipeados (Lista de T, Procesador de T, etc.). Son no mutuamente excluyentes.

Usted puede tener esta opción si desea:

public class Base<T> 
{ 

} 

public class Derived : Base<Foo> 
{ 

} 
+0

Y, de hecho, puede tener interfaces genéricas: interfaz pública IBase -> público base : IBase -> public class Derivado: Base

4

Creo que debería usar genéricos cuando solo desea aplicar la misma funcionalidad a varios tipos (Agregar, Eliminar, Contar) y se implementará de la misma manera. La herencia es cuando necesita la misma funcionalidad (GetResponse) pero desea que se implemente de diferentes maneras.

+0

IMO, ¡esta es en realidad la mejor respuesta a esta pregunta! Después de buscar SE durante unos 20 minutos ... – Pingi

7

Utilice los genéricos para especificar un algoritmo o comportamiento de tipo que se pueda expresar en términos de algún "tipo desconocido" mientras se mantiene una API fuertemente tipada en términos de ese tipo desconocido. El tipo desconocido que se conoce como un parámetro de tipo y se expresa en el código como el siguiente:

public class List<T> 
{ 
    public void Add(T item) 
} 

(etc) - T aquí es el parámetro de tipo. métodos genéricos son similares:

public void Foo<T>(T item) 

El llamando código especifica el argumento tipo que quiere trabajar con, por ejemplo,

List<string> list = new List<string>(); 
list.Add("hi"); 

Use inheritance para especializar el comportamiento de un tipo.

Realmente no puedo pensar en muchos lugares donde son alternativas entre sí ...

+0

Downvoters: indique las razones ... –

+1

+1 Para obtener una definición concisa de "programación genérica". –

+3

Si bien no lo rechacé, su respuesta es inútil. El OP es obviamente nuevo en .NET y su definición de diccionario extremadamente corta y concisa probablemente hará muy poco para aclarar su confusión. – BFree

4

Use genéricos cuando se quiere crear una "plantilla" que puede aplicarse a muchos estilos de clases desconocidas. P.ej. ¿Colecciones sosteniendo? son buenos candidatos para genéricos. La herencia es para cuando tienes un conocimiento base de que los niños "son" una extensión de ese concepto.

Mis reglas generales

  • si comienza a definir properites como objetos en el código y la conversión de tipos mucho, entonces es probable que sea hora de los genéricos.
  • Si desea programar contra el "concepto superior", así como la clase derivada, entonces su herencia.
  • Si su clase va a envolver o trabajar en una clase concerte, entonces son genéricos.
  • Si confía en los detalles de una clase desconocida "aún por definir", entonces probablemente sea mejor con genéricos.
  • Si las clases derivadas son "es una", entonces suele ser herencia
  • Si su superclase "usa alguna x", entonces son genéricos.
+0

¡Ahora puede comentar! – Vaccano

Cuestiones relacionadas