inheritance - programming - ¿Debería subclasificar la Lista<T> o tenerla como una propiedad?
polymorphism oop (8)
Me he enfrentado a este problema con bastante frecuencia durante los últimos meses, durante los cuales he estado construyendo este sistema. El escenario es el siguiente: tengo este tipo de objeto que esencialmente es una lista de otros objetos, pero tiene otras propiedades específicas de su naturaleza. Por ejemplo:
-
Tests
clase:- Contiene muchos objetos de
Test
- Tiene propiedades:
-
DefaultTimeouts
-
DefaultNumberOfTries
-
- Contiene muchos objetos de
¿Debería tener esta subclase de clase List<Test>
o debería heredar de Object
, simplemente teniendo la lista como una propiedad junto a los otros campos?
Sé que esto puede ser un poco subjetivo y el gusto personal podría tener un papel aquí, pero me gustaría saber su opinión al respecto.
"Favorecer la composición sobre la herencia" es siempre una buena regla empírica. ¿Los métodos que usan esta clase usan todos los métodos de la Lista, así como los que agrega o solo los que agrega?
Al leer las respuestas, parece que la pregunta clave es ¿a qué longitud su objeto es realmente una lista? Entonces, tal vez un buen compromiso entre los peligros de la herencia y la falta de transparencia de la composición sería tener una List<Test>
como un backend privado y exponer solo los métodos que se usarían.
Contrariamente a la mayoría de las respuestas aquí, no sería una subclase de la lista en la mayoría de los casos. Descubrí que heredar de una clase para reutilizar la funcionalidad generalmente causa problemas más adelante.
Normalmente solo tengo una propiedad de tipo List (o IList) que devuelve una referencia a la lista. Por lo general, solo necesita obtener una propiedad aquí. Puede controlar el acceso a la lista eligiendo devolver una versión de solo lectura de la lista con .AsReadOnly () o simplemente exponiendo la lista como un IEnumerable.
En los casos en que deseo que las Pruebas sean una lista, generalmente implemento IList y llamo a un campo de Lista interna para las implementaciones reales de IList. Esto es un poco más laborioso y da como resultado más código para mantener, pero he descubierto que es mejor mantenerlo que heredar la Lista solo por su implementación.
En su ejemplo, dijo "Las pruebas de clase contienen muchos objetos de prueba", no "Las pruebas de clase son una colección de objetos de prueba". IMO no es necesario subclasificar la Lista en este escenario a menos que necesite tener una interfaz tipo Lista para esta clase.
Sin embargo, la respuesta realmente depende del contexto de la clase de Pruebas. Si se comporta como Lista y se usará en contextos donde se espera Lista de objetos, herede de Lista.
Tenga en cuenta que la herencia es más difícil de mantener que la composición.
Además, cambiaría el nombre de Tests a TestCollection (si subclase List), o algo así como TestUnit (si contiene una lista de clases de prueba).
La herencia generalmente se asigna a una relación "es-a". Como su contenedor es una lista, pero con algunas otras cosas, heredaría de List y agregaría sus propiedades adicionales a su subclase.
No creo que lo que tienes es una simple "lista de pruebas", porque necesitabas algo más. Sugeriría que lo llames TestSuite
y que la Lista sea una propiedad. Has-a es mucho más fácil de mantener en comparación con la herencia.
En general, tendría mucho cuidado de heredar algo así como una List
.
Si literalmente hace todo lo que una List
haría, y todas las funciones de la List
actuarían en el objeto Tests
de una manera intuitiva que da el resultado correcto, entonces en mi opinión debería simplemente subclase List<Test>
.
De lo contrario, tendrá una clase con una tonelada de métodos que solo llaman a un método del mismo nombre en la variable List<Test>
en la instancia. Eso solo será una extensión imperfecta de la clase List<Test>
.
Subclase de List <T>. Si tiene la Lista genérica como una propiedad, no está tan bien encapsulada como una subclase.
Si parece una Lista <T> y suena como una Lista <T>, probablemente sea una Lista <T>.
Yo lo llamaría TestCollection.