1. Pegaso
Echemos un vistazo más profundo al tercer principio de la programación orientada a objetos : la herencia . Este es un tema muy interesante que usará a menudo. Para los no iniciados, la programación es indistinguible de la magia. Entonces, comencemos con una analogía interesante...;
Digamos que eres un mago que quiere crear un caballo volador. Por un lado, podrías intentar conjurar un pegaso. Pero como los pegasos no existen en la naturaleza, esto será muy difícil. Tendrás que hacer mucho tú mismo. Es mucho más fácil tomar un caballo y conjurar sus alas.
En programación, este proceso se llama "herencia". Suponga que necesita escribir una clase muy compleja. Lleva mucho tiempo escribir código desde cero y luego probar todo durante mucho tiempo para buscar errores. ¿Por qué ir por el camino difícil? Es mejor mirar para ver si tal clase ya existe.
Suponga que encuentra una clase cuyos métodos implementan el 80% de la funcionalidad que necesita. ¿Qué haces con eso a continuación? Podría simplemente copiar su código en su clase. Pero esta solución tiene varios inconvenientes:
- Es posible que la clase que encuentre ya esté compilada en un código de bytes y es posible que no tenga acceso a su código fuente.
- El código fuente de la clase está disponible, pero usted trabaja para una empresa que podría ser demandada por un par de miles de millones por usar incluso 6 líneas del código de otra persona. Y luego su empleador lo demandará.
- Duplicación innecesaria de una gran cantidad de código. Además, si el autor de una clase externa encuentra un error y lo corrige, aún tendrá el error.
Hay una solución más elegante y no requiere obtener acceso legal al código de la clase original. En Java, simplemente puede declarar esa clase como el padre de su clase. Eso será equivalente a agregar el código de esa clase a su propio código. Su clase verá todos los datos y todos los métodos de la clase principal. Por ejemplo, puedes hacer esto: heredamos "caballo" y luego agregamos "alas" para obtener un "pegaso"
2. Clase base común
La herencia también se puede utilizar para otros fines. Digamos que tiene diez clases que son muy similares. Tienen los mismos datos y métodos. Puede crear una clase base especial, mover los datos (y los métodos asociados) a esta clase base y declarar esas diez clases como descendientes. En otras palabras, en cada clase indique que su clase padre es esta clase base.
Así como las ventajas de la abstracción se revelan solo junto con la encapsulación lateral, también se mejoran mucho las ventajas de la herencia cuando se usa el polimorfismo. Pero aprenderás sobre eso un poco más tarde. Hoy veremos varios ejemplos del uso de la herencia.
Piezas de ajedrez
Supongamos que estamos escribiendo un programa que juega al ajedrez con un usuario humano. En consecuencia, necesitamos clases para representar las piezas. ¿Qué clases serían?
Si alguna vez has jugado al ajedrez, la respuesta obvia es el rey, la reina, el alfil, el caballo, la torre y el peón.
Pero las clases mismas aún necesitarían almacenar información sobre cada pieza. Por ejemplo, las coordenadas x e y, y el valor de la pieza. Después de todo, algunas piezas son más valiosas que otras.
Además, las piezas se mueven de manera diferente, lo que significa que las clases implementarán un comportamiento diferente. Así es como podría definirlos como clases:
|
|
|
|
|
|
Esta es una descripción muy primitiva de las piezas de ajedrez.
Clase base común
Y así es como podría usar la herencia para reducir la cantidad de código. Podemos llevar los métodos y datos comunes a una clase común. Lo llamaremos ChessItem
. No tiene sentido crear objetos del ChessItem class
, ya que la clase no corresponde a ninguna pieza de ajedrez . Dicho esto, la clase resultará muy útil:
|
|
|
|
||
|
|
|
Esta es una excelente manera de simplificar el código para objetos similares. Los beneficios son particularmente notables cuando hay miles de objetos diferentes y cientos de clases en el proyecto. Por lo tanto, las clases principales (base) seleccionadas correctamente le permiten no solo simplificar en gran medida la lógica, sino también reducir el código diez veces.
3. Herencia de clases —extends
Entonces, ¿qué se necesita para heredar una clase? Para que una clase herede otra, debe escribir la extends
palabra clave después de la declaración de la clase secundaria y luego escribir el nombre de la clase principal. Por lo general, se ve algo como esto:
class Descendant extends Parent
Esto es lo que debe escribir al declarar la clase Descendant. Por cierto, una clase puede heredar solo una clase.
En la imagen, vemos que una vaca heredó un cerdo, que heredó una gallina, que heredó un huevo. ¡Un solo padre! Tal herencia no siempre es lógica. Pero cuando todo lo que tienes es un cerdo y realmente necesitas una vaca, los programadores a menudo no pueden resistir el impulso de convertir a un cerdo en una vaca.
Java no tiene herencia múltiple: una clase no puede heredar dos clases. Cada clase puede tener solo una clase principal. Si no se especifica ninguna clase principal, la clase principal es Object
.
Dicho esto, Java tiene herencia múltiple de interfaces. Esto mitiga ligeramente el problema. Hablaremos de las interfaces un poco más tarde, pero por ahora sigamos explorando la herencia.