¡Hola! Hoy vamos a echar un vistazo más de cerca a un principio de la Programación Orientada a Objetos (OOP): Herencia. También estudiaremos otros tipos de relaciones entre clases: composición y agregación.
Este tema no será difícil: ya se ha encontrado con herencia y ejemplos de herencia muchas veces en lecciones anteriores. Hoy lo principal será reforzar tus conocimientos, profundizar en el mecanismo de la herencia y volver a repasar algunos ejemplos. :) ¡Bueno, vamos!
Cuando tenemos un par de docenas de clases de automóviles, la cantidad de código duplicado se vuelve realmente grave. Mover campos y métodos comunes (también llamados "estados" y "comportamientos") a una clase principal nos permite ahorrar mucho tiempo y espacio. Si algún tipo tiene propiedades o métodos únicos que otros tipos de automóviles no tienen, no hay problema. Siempre puede crearlos en una clase descendiente, separados de todos los demás.
Lo mismo ocurre con los campos: si una clase secundaria tiene propiedades únicas, declaramos tranquilamente estos campos dentro de la clase secundaria y dejamos de preocuparnos. :) La capacidad de reutilizar el código es la principal ventaja de la herencia. Para los programadores, es muy importante no escribir código extra. Te encontrarás con esto repetidamente en tu trabajo. Recuerde algo más crucial: Java no tiene herencia múltiple. Cada clase hereda solo una clase. Hablaremos más sobre las razones de esto en futuras lecciones. Por ahora, solo recuérdalo. Por cierto, esto hace que Java sea diferente de otros lenguajes OOP. Por ejemplo, C++ admite la herencia múltiple. Todo queda más o menos claro con la herencia. Vamonos.
![Relaciones entre clases. Herencia, composición y agregación - 1](https://cdn.codegym.cc/images/article/d2bb735f-0287-4fd1-9d3f-a346063f7f86/512.jpeg)
Herencia en Java y sus ventajas
Como seguramente recordará, la herencia es un mecanismo que le permite describir una nueva clase basada en una clase existente (clase padre). Al hacerlo, la nueva clase toma prestadas las propiedades y la funcionalidad de la clase principal. Recordemos un ejemplo de herencia dado en lecciones anteriores:
public class Car {
private String model;
private int maxSpeed;
private int yearOfManufacture;
public Car(String model, int maxSpeed, int yearOfManufacture) {
this.model = model;
this.maxSpeed = maxSpeed;
this.yearOfManufacture = yearOfManufacture;
}
public void gas() {
// Gas
}
public void brake() {
// Brake
}
}
public class Truck extends Car {
public Truck(String model, int maxSpeed, int yearOfManufacture) {
super(model, maxSpeed, yearOfManufacture);
}
}
public class Sedan extends Car {
public Sedan(String model, int maxSpeed, int yearOfManufacture) {
super(model, maxSpeed, yearOfManufacture);
}
}
Tenemos un cierto programa que implica trabajar con varios tipos de automóviles. Incluso si no eres un entusiasta de los automóviles, probablemente sepas que hay muchos tipos de automóviles en el mundo. :) En consecuencia, separaremos las propiedades comunes de los automóviles en una clase principal común llamada Car
. Entonces, ¿qué es común a todos los automóviles, independientemente de su tipo? Cada automóvil tiene un año de fabricación, un nombre de modelo y una velocidad máxima. Ponemos estas propiedades en los campos model
, maxSpeed
y yearOfManufacture
. En cuanto al comportamiento, cualquier coche puede acelerar y frenar. :) Definimos este comportamiento en el gas()
ybrake()
métodos. ¿Qué beneficios nos da esto? En primer lugar, reduce la cantidad de código. Por supuesto, podemos prescindir de la clase padre. Pero dado que cada automóvil debe poder acelerar y desacelerar, tendremos que crear métodos gas()
y brake()
en las clases Truck
, Sedan
, F1Car
y SportsCar
y en todas las demás clases de automóviles. Imagina cuánto código adicional tendríamos que escribir. Y no te olvides de los campos model
, maxSpeed
y yearOfManufacture
: si nos deshacemos de la clase principal, ¡tendremos que crearlos en cada clase de automóvil! ![Relaciones entre clases. Herencia, composición y agregación - 2](https://cdn.codegym.cc/images/article/98043e55-ad3d-4491-a097-aeeaf4a5b23b/800.jpeg)
public class F1Car extends Car {
public void pitStop() {
// Only race cars make pit stops
}
public static void main(String[] args) {
F1Car formula1Car = new F1Car();
formula1Car.gas();
formula1Car.pitStop();
formula1Car.brake();
}
}
Veamos los autos de carrera de Fórmula Uno como ejemplo. A diferencia de sus "parientes", tienen un comportamiento único: hacen una parada técnica de vez en cuando. Esto no nos molesta. Ya hemos descrito el comportamiento común en la Car
clase principal y el comportamiento específico de las clases descendientes se puede agregar a esas clases. ![Relaciones entre clases. Herencia, composición y agregación - 3](https://cdn.codegym.cc/images/article/1efa1875-4766-4044-a566-42ffda92c951/800.jpeg)
Composición y agregación
Las clases y los objetos se pueden vincular entre sí. La herencia describe una relación "es-un". Un león es un animal. Tal relación se expresa fácilmente usando la herencia, dondeAnimal
es la clase padre y Lion
es la clase secundaria. Sin embargo, no todas las relaciones se describen de esta manera. Por ejemplo, un teclado definitivamente está relacionado con una computadora, pero no es una computadora . Las manos están relacionadas de alguna manera con una persona, pero no son una persona. En estos casos, tenemos otro tipo de relación: no "es-un", sino "tiene-un". Una mano no es una persona, pero es parte de una persona. Un teclado no es una computadora, pero es parte de una computadora. Una relación tiene-un se puede describir en código usando composición y agregación. La diferencia radica en el "rigor" de la relación. Pongamos un ejemplo sencillo: Tenemos una Car
clase. Todo coche tiene un motor. Además, cada automóvil tiene pasajeros. ¿ Cuál es la diferencia fundamental entre los campos Engine engine
y ? Passenger[] passengers
El hecho de que el pasajero A
esté sentado en un automóvil no significa que los pasajeros B
no C
estén en el automóvil. Un coche puede corresponder a varios pasajeros. Además, si todos los pasajeros salen de un automóvil, seguirá funcionando sin problemas. La relación entre la Car
clase y la Passenger[] passengers
matriz es menos estricta. Se llama agregación . Proporciona otro buen ejemplo de agregación. Supongamos que tenemos una Student
clase y unStudentGroup
clase. Un estudiante puede unirse a múltiples organizaciones estudiantiles: un club de física, un club de fans de Star Wars y/o un club de comedia estudiantil. La composición es un tipo más estricto de relación. Al usar composición, un objeto es parte de algún objeto y no puede pertenecer a otro objeto del mismo tipo. El ejemplo más simple es el motor de un automóvil. Un motor es parte de un automóvil y no puede ser parte de otro automóvil. Como puede ver, su relación es mucho más estricta que la relación entre Car
y Passengers
. ![Relaciones entre clases. Herencia, composición y agregación - 4](https://cdn.codegym.cc/images/article/c94d95f0-e723-4416-a219-22aaef09b567/800.jpeg)
GO TO FULL VERSION