Oracle_One-Alura_Latam/008_java_oo/herencia_interfaces.md

276 lines
7.9 KiB
Markdown

# Java [Polimorfismo, Entendiendo Herencia e Interfaces](https://app.aluracursos.com/course/java-parte-3-entendiendo-herencia-interfaces)
## Herencia
Extendiendo la funcionalidad de la clase **Funcionario** a la nueva clase **Gerente**,
heradando métodos y atributos de la case padre (Funcionario), utilzando la palabra
reservada `extends`. Reutilización de código.
Palabras reservadas `this` y `super`.
- **this**: este *keyword* se refiere al objeto catuan en un método o
constructor. El uso más común de este término es eliminnar la ambiguedad entre
los atributos de clase y los parámetros con el mismo nombre. Además sirve para:
- Invocar al constructor de la clase actual.
- Invocar al método de clase actual.
- Devolver el objeto de la clase actual.
- Pasar un argumento en la llamada a un método.
- Pasar un arg. en la llamada al constructor.
- **super**: este *keyword* se refiere a objetos de la superclase (madre). Se
utiliza para llamar a los métodos de la superclase y para acceder al constructor
de esta. Su función más común es eliminar la ambiguedad entre superclases y
subclases que tienen métodos con el mismo nombre. Utilizada para:
- `super`:
- Referirse a la variable de instancia de la clase inmediatamente superior.
- Invocar métodos de la clase inmediatamente superior (clase madre).
- `super()`:
- Invocar al constructor de la clase inmediatamente superior (clase madre).
Java doc, [this](https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html)
y [super](https://docs.oracle.com/javase/tutorial/java/IandI/super.html)
### Modificadores de acceso
Los modificadores de acceso o accesibilidad son algunas palabras claves utilizadas
en el lenguaje Java para definir el nivel de accesibilidad que los elementos de
una clase (atributos y métodos) e incluso la propia clase puede tener los mismos
elementos de otra clase.
- **Public**: Este es el modificador menos restrictivo de todos. De esta manera,
cualquier componente puede acceder a los miembros de la clase, las clases y las
interfaces.
- **Protected**: Al usar este modificador de acceso, los miembros de la clase y
las clases son accesibles para otros elementos siempre que están dentro del
mismo package o, si pertenecen a otros packages, siempre que tengan una relación
extendida (herencia), es decir, las clases secundarias pueden acceder a los
miembros de su clase principal (o clase de abuelos, etc.).
- **Private**: Este es el modificador de acceso más restrictivo de todos.
Solo se puede acceder a los miembros definidos como privados desde dentro de la
clase y desde ningún otro lugar, independientemente del paquete o la herencia.
Java doc
[modificadores de acceso](https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html)
### Sobrecarga de metodo
```java
public boolean autenticar(int password) {
if (this.password == contraseña) {
return true;
} else {
return false;
}
}
// Nuevo método, recibiendo dos parámetros
public boolean autenticar(String login, int password) {
...
}
```
Se ha creado una nueva versión del método autenticar. Ahora tenemos dos métodos
de autenticar en la misma clase que varían en el número o tipo de parámetros.
Esto se llama sobrecarga de métodos.
La sobrecarga no tiene en cuenta la visibilidad o retorno del método, solo los
parámetros y no depende de la herencia.
Notas:
- La clase madre es llamada de super o base class.
- La clase hija también es llamada de sub class.
- Aumentar la visibilidad de un miembro (atributo, método) a través de protected.
- Acceder o llamar un miembro (atributo, método) a través de super.
## Entendiendo Polimorfismo
Clase Madre
```java
public class Vehiculo {
public void encender() {
System.out.println("Enciendiendo vehículo");
}
}
```
Clases Hijas
```java
public class Automovil extends Vehiculo {
public void encender() {
System.out.println("Enciendiendo automovil");
}
}
```
```java
public class Motocicleta extends Vehiculo {
public void encender() {
System.out.println("Enciendiendo motocicleta");
}
}
```
Main
```java
public class TestVehiculos {
public static void main(String[] args) {
Vehiculo m = new Motocicleta();
m.encender();
Vehiculo c = new Automovil();
c.encender();
}
}
```
Salida
```txt
Enciendiendo motocicleta
Enciendiendo automovil
```
Notas
- Los objetos no cambian de tipo.
- La referencia puede cambiar, y ahí es donde entra el polimorfismo.
- El polimorfismo permite utilizar referencias más genéricas para comunicarse
con un objeto.
- El uso de referencias más genéricas permite **desacoplar** sistemas.
- Uso de la anotación `@Override`.
- Los constructores no se heredan.
- Se puede llamar a un constructor de clase madre mediante `super()`.
## Clases abstractas e interfaces
| [Interfáz](https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html) | [Clase Abstracta](https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html) |
| - | - |
| *Keyword* `implements` | *Keyword* `extends` |
| Admite herencia múltiple | No admite herencia múltiple |
| Proporciona una abstracción absoluta y no puede tener implementaciones de métodos | Puede tener métodos con implementaciones |
| No posee constructor | Posee constructor |
| No puede tener modificador de acceso, todos los accesos con públicos | Puede tener modificadores de acceso |
| Sus miembros **no** pueden ser `static` | Solo los miembros completamenten abstractos pueden ser `static` |
No hay herencia múltiple en Java, Las interfaces son una alternativa a la
herencia con respecto al polimorfismo.
Java [util](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/package-summary.html)
#### Ejemplos de clases abstractas e interfaces
Clase **Abstracta**
[Funcionario](./eclipse/bytebank_heredado/src/bytebank_heredado/Funcionario.java)
```java
public abstract class Funcionario {
private String nombre;
private String documento;
private Double salario;
private int tipo;
public Funcionario() {
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getDocumento() {
return documento;
}
public void setDocumento(String documento) {
this.documento = documento;
}
public Double getSalario() {
return salario;
}
public void setSalario(Double salario) {
this.salario = salario;
}
public int getTipo() {
return tipo;
}
public void setTipo(int tipo) {
this.tipo = tipo;
}
public abstract double getBonificacion();
}
```
Implementada por la **clase**
[Gerente](./eclipse/bytebank_heredado/src/bytebank_heredado/Gerente.java)
```java
public class Gerente extends Funcionario implements Autenticable {
private AutenticacionUtil util;
public Gerente() {
this.util = new AutenticacionUtil();
}
public double getBonificacion() {
return super.getSalario() + (this.getSalario() * 0.5);
}
@Override
public void setClave(String clave) {
this.util.setClave(clave);
}
@Override
public boolean inicioSesion(String clave) {
return this.util.inicioSesion(clave);
}
}
```
Que implementa la **Interfáz**
[Autenticable](./eclipse/bytebank_heredado/src/bytebank_heredado/Autenticable.java)
```java
public interface Autenticable {
public void setClave(String clave);
public boolean inicioSesion(String clave);
}
```
Utilización de clase **utilitaria**
[Autenticable](./eclipse/bytebank_heredado/src/bytebank_heredado/AutenticacionUtil.java)
```java
public class AutenticacionUtil {
private String clave;
public boolean inicioSesion(String clave) {
return this.clave == clave;
}
public void setClave(String clave) {
this.clave = clave;
}
}
```