Saltar al contenido principal
Página

Tema 1.3 - Pilares POO

La POO posee varios pilares para asegurar la simplicidad y reutilización del código, y aunque diversos autores señalan diversos pilares, en este documento se considerarán los cuatro que son comunes en la mayoría de textos, estos son: Abstracción, Encapsulamiento, Herencia y Polimorfismo, las dos primeras están más relacionadas

 con la búsqueda de códigos simples y las dos siguientes con la reutilización.


Encapsulamiento (Modificadores de Acceso)

Los modificadores de acceso en java, como su nombre indica, determinan desde qué clases se puede acceder a un determinado elemento.

En Java tenemos 4 tipos: public , private , protected y el tipo por defecto, que no tiene ninguna palabra clave asociada, pero se suele conocer como default o package-private.




Veamos algunos ejemplos de cada uno de los modificadores:


Ejemplo  de Clase Default

Cuando un modificador de acceso no es indicado en la declaración, entonces java asume que es un modificador por defecto. Clases, atributos y métodos sin modificador  de acceso sólo son visibles en el mismo paquete. Un error en tiempo de ejecución sería lanzado en caso de tratar de de acceder desde un paquete diferente.


Nótese que la clase se encuentra dentro del paquete vehicle. Veamos que sucede al crear una instancia de la clase Car desde otra clase dentro y fuera del paquete


Al tratar de crear un objeto de la clase Car desde una clase perteneciente a otro paquete veremos que al compilar el código un error es lanzado ya que la clase no es accesible desde fuera del paquete Vehicle.




Ejemplo de Atributos Default

Si un atributo de la clase no tiene modificador de acceso, entonces éste es solamente accesible desde una clase dentro del mismo paquete




Nótese que los atributos de la clase Car no tienen modificadores de acceso y la clase se encuentra dentro del paquete vehicle.

Veamos que sucede cuando se crea un objeto de la clase Car desde otra clase dentro y fuera del paquete vehicle.




Al tratar de crear un objeto de la clase Car desde una clase perteneciente a otro paquete veremos que al compilar el código un error es lanzado ya que los atributos no son accesibles desde fuera del paquete Vehicle.



Ejemplo  de Método Default

Si un método no tiene declarado un modificador de acceso entonces el método es accesible por las clases dentro del mismo paquete.




Nótese que  el método DisplayCharacteristics de la  clase Car, no posee modificador de acceso y que se encuentra dentro del paquete vehicle. Veamos que sucede cuando se intenta acceder al método desde una clase dentro y fuera del paquete vehicle. 




Al tratar de llamar un método de la clase Car desde una clase perteneciente a otro paquete veremos que no es posible acceder a dicho método ya que éste no es accesible desde fuera del paquete Vehicle.


Ejemplo Modificador de Acceso Public:

  1. Cuando el modificador de acceso de clases, métodos o atributos es declarado public, significa que puede ser accedido desde cualquier paquete.
  2. Ahora tu vas a construir el ejemplo, cambia el modificador de acceso a public para los tres escenarios anteriores en donde se intentaba acceder desde una clase fuera del paquete vehicle. 

Ejemplo Modificador de Acceso Private:

  1. Cuando se declara un método o atributo como private, se está indicando que  éstos sólo son visibles dentro de la misma clase. Este modificador de acceso es principalmente usado en métodos y atributos ya que no tiene mucho sentido declarar una clase de tipo privado. Cuando se trata de acceder a un método o atributo de tipo private desde una clase de otro paquete o incluso del mismo paquete, un mensaje de error es mostrado.
  2. Ahora tu vas a construir el ejemplo, cambia el modificador de acceso a private para los tres escenarios anteriores en donde se intentaba acceder desde una clase fuera del paquete vehicle. 
  3. Modificador de Acceso Protected.
  4. Se verá en detalle cuando se vea el concepto de Herencia.


Herencia

En la programación orientada a objetos (OOP), la herencia permite reutilizar el software extendiendo un miembro existente de la clase. Al crear una nueva clase, es posible que la nueva clase herede los atributos y métodos de una clase existente en lugar de implementar los mismos atributos y métodos nuevamente en la nueva clase. Aquí, la clase existente se llama superclase y la nueva clase se llama subclase.

Por ejemplo, un Círculo es una Forma. Por lo tanto, en Java, se puede decir que el círculo de clases hereda de la clase Forma. En este contexto, la clase Forma es una superclase y la clase Circulo es una subclase.

En Java, la herencia se declara utilizando la palabra clave extends. 


Modificador de Acceso Protected:

Además de los modificadores de acceso public y private, el acceso protected ofrece un nivel intermedio de acceso entre ellos. Recuerde que los miembros privados de una superclase no son accesibles para otras clases, incluidas sus subclases.

Sin embargo, los miembros protegidos de una superclase son accesibles desde sus subclases. Sin embargo, es diferente de los miembros públicos, a los que se puede acceder mediante cualquier clase, independientemente de la relación de herencia. Los miembros públicos y protegidos son similares en el hecho de que sus modificadores de acceso originales se conservan en las subclases: los miembros públicos de la superclase se convierten en miembros públicos de la subclase y los miembros protegidos de la superclase se convierten en miembros protegidos de la subclase.

En palabras más simples, vea la herencia como un copy-pasteque nos permite reutilizar código.


Ejemplo de Herencia:

Vamos a simular el comportamiento que tendrían los diferentes integrantes de la selección  de fútbol; tanto los Futbolistas como el cuerpo técnico (Entrenadores, Masajistas, etc…). Para simular este comportamiento vamos a definir tres clases que van a representaran a objetos Futbolista, Entrenador y Masajista. De cada unos de ellos vamos a necesitar algunos datos que reflejaremos en los atributos y una serie de acciones que reflejaremos en sus métodos. Estos atributos y métodos los mostramos en el siguiente diagrama de clases:



Como se puede observar, vemos que en las tres clases tenemos atributos y métodos que son iguales ya que los tres tienen los atributos id, Nombre, Apellidos y Edad; y los tres tienen los métodos de Viajar y Concentrarse:



Lo que podemos ver en este punto es que tendríamos mucho código repetido ya que las tres clases tienen métodos y atributos comunes, es por ello que se dice que la herencia consiste en "sacar factor común" para no escribir código de más, por tanto lo que haremos será crear una clase con el "código que es común a las tres clases" (a esta clase se le denomina en la herencia como "Clase Padre o SuperClase") y el código que es  especifico de cada clase, lo dejaremos en ella, siendo denominadas estas clases como "Clases Hijas", las cuales heredan de la clase padre todos los atributos y métodos públicos o protegidos.

Es muy importante decir que las clases hijas no van a heredar nunca los atributos y métodos privados de la clase padre. En resumen, al "sacar factor común" y aplicar herencia, tenemos las siguientes clases:



A nivel de código se tiene:

package herencia;

import java.util.ArrayList;

public class Main {

 // ArrayList de objetos SeleccionFutbol. Idenpendientemente de la clase hija a la que pertenezca el objeto
  public static ArrayList<SeleccionFutbol> integrantes = new ArrayList<SeleccionFutbol>();

 public static void main(String[] args) {
  Entrenador pekerman = new Entrenador(1, "Jose Nestor", "Pekerman", 60, "284EZ89");
  Futbolista james = new Futbolista(2, "James", "Rodriguez", 26, 6, "Volante 10");
  Masajista raulMartinez = new Masajista(3, "Raúl", "Martinez", 41, "Licenciado en Fisioterapia", 18);

  integrantes.add(pekerman);
  integrantes.add(james);
  integrantes.add(raulMartinez);

  // CONCENTRACION
  System.out.println("Todos los integrantes comienzan una concentracion. (Todos ejecutan el mismo método)");
  for (SeleccionFutbol integrante : integrantes) {
   System.out.print(integrante.getNombre()+" "+integrante.getApellidos()+" -> ");
   integrante.concentrarse();
  }

  // VIAJE
  System.out.println("\nTodos los integrantes viajan para jugar un partido. (Todos ejecutan el mismo método)");
  for (SeleccionFutbol integrante : integrantes) {
   System.out.print(integrante.getNombre()+" "+integrante.getApellidos()+" -> ");
   integrante.viajar();
  }
  
  /* ENTRENAMIENTO
   * A continuación se va a ejecutar código especifico de las clases hijas
   * de ahi que ahora no podamos recorrer el ArrayList y ejecutar el mismo método para todos los objetos
   * ya que ahora esos objetos son únicos de la clases hijas.
   */
  
  System.out.println("\nEntrenamiento: Solamente el entrenador y el futbolista tiene metodos para entrenar:");
  System.out.print(pekerman.getNombre() + " " + pekerman.getApellidos() + " -> ");
  pekerman.dirigirEntrenamiento();
  System.out.print(james.getNombre() + " " + james.getApellidos() + " -> ");
  james.entrenar();

  // MASAJE
  System.out.println("\nMasaje: Solo el masajista tiene el método para dar un masaje:");
  System.out.print(raulMartinez.getNombre() + " " + raulMartinez.getApellidos( ) + " -> ");
  raulMartinez.darMasaje();

  // PARTIDO DE FUTBOL
  System.out.println("\nPartido de Fútbol: Solamente el entrenador y el futbolista tiene metodos para el partido de fútbol:");
  System.out.print(pekerman.getNombre() + " " + pekerman.getApellidos() + " -> ");
  pekerman.dirigirPartido();
  System.out.print(james.getNombre() + " " + james.getApellidos() + " -> ");
  james.jugarPartido();

 }

}

Para la clase selección de fútbol se tiene:

package herencia;

public class SeleccionFutbol {
 
 protected int id;
 protected String nombre;
 protected String apellidos;
 protected int edad;
 
 //Geters y Setters
 public int getId() {
  return id;
 }
 public void setId(int id) {
  this.id = id;
 }
 public String getNombre() {
  return nombre;
 }
 public void setNombre(String nombre) {
  this.nombre = nombre;
 }
 public String getApellidos() {
  return apellidos;
 }
 public void setApellidos(String apellidos) {
  this.apellidos = apellidos;
 }
 public int getEdad() {
  return edad;
 }
 public void setEdad(int edad) {
  this.edad = edad;
 }
 
 // Constructor de la clase
 public SeleccionFutbol() {
 }
 
 //Métodos de la clase
 public void concentrarse() {
  System.out.println("Concentrarse");
 }
 
 public void viajar() {
  System.out.println("Viajar");
 }

}

Para la clase futbolista se tiene:

package herencia;

public class Futbolista extends SeleccionFutbol{
 
 //Atributos de la clase Futbolista
 private int dorsal;
 private String numero;
 
 //Getters y Setters
 public int getDorsal() {
  return dorsal;
 }

 public void setDorsal(int dorsal) {
  this.dorsal = dorsal;
 }

 public String getNumero() {
  return numero;
 }

 public void setNumero(String numero) {
  this.numero = numero;
 }
 
 //Constructor de la Clase Futbolista
 public Futbolista() {
  super();
 }
 
 //Métodos propios de la clase Futbolista
 public void jugarPartido() {
  System.out.println("Juega un partido");
 }

 public void entrenar() {
  System.out.println("Entrena");
 }
 

}

Para la clase entrenador es:

package herencia;

public class Entrenador extends SeleccionFutbol{

 //Atributos de la clase Entrenador
 private String idFederacion;
 
 //Getters y Setters
 public String getIdFederacion() {
  return idFederacion;
 }

 public void setIdFederacion(String idFederacion) {
  this.idFederacion = idFederacion;
 }

 //Constructor de la Clase Entrenador
 public Entrenador() {
  super();
 }
 
 //Métodos propios de la clase Entrenador
 public void dirigirPartido() {
  System.out.println("Dirige un partido");
 }

 public void dirigirEntreno() {
  System.out.println("Dirige un entrenamiento");
 }

}

Y finalizando la clase masajista tiene:

package herencia;

public class Masajista extends SeleccionFutbol{
 
 //Atributos de la clase Masajista
 private String titulacion;
 private int aniosExperiencia;
 
 //Getters y Setters
 public String getTitulacion() {
  return titulacion;
 }

 public void setTitulacion(String titulacion) {
  this.titulacion = titulacion;
 }

 public int getAniosExperiencia() {
  return aniosExperiencia;
 }

 public void setAniosExperiencia(int aniosExperiencia) {
  this.aniosExperiencia = aniosExperiencia;
 }
 
 //Constructor de la clase Masajista
 public Masajista() {
  super();
 }
 
 //Métodos de la clase Masajista
 public void darMasaje() {
  System.out.println("Dar masaje");
 }

}


Como se puede observar ahora queda un código mucho más limpio, estructurado y con menos líneas de código, lo que lo hace más legible, cosa que es muy importante y lo que todavía lo hace más importante es que es un código reutilizable, lo que significa que ahora si queremos añadir más clases a nuestra aplicación como por ejemplo una clase Médico, Utillero, Jefe/a de prensa etc. que pertenezcan también al equipo técnico de la selección de futbol, lo podemos hacer de forma muy sencilla ya que en la clase padre (SeleccionFutbol) tenemos implementado parte de sus datos y de su comportamiento y solo habrá que implementar los atributos y métodos propios de esa clase.


Ahora bien se explicará en detalle palabras reservadas  extends, protected y super:

  • Extends: Esta palabra reservada, indica a la clase hija cual va a ser su clase padre, es decir que por ejemplo en la clase Futbolista al poner "public class Futbolista extends SeleccionFutbol" le estamos indicando a la clase 'Futbolista' que su clase padre es la clase 'SeleccionFutbol' o dicho de otra manera para que se entienda mejor, al poner esto estamos haciendo un "copy-paste dinámico" diciendo a la clase 'Futbolista' que se 'copie' todos los atributos y métodos públicos o protegidos de la clase SeleccionFutbol.
  • Protected:  Sirve para indicar un tipo de visibilidad de los atributos y métodos de la clase padre y significa que cuando un atributo es 'protected' o protegido, solo es visible ese atributo o método desde una de las clases hijas y no desde otra clase.
  • Super: Sirve para llamar al constructor de la clase padre. 


Polimorfismo

El término Polimorfismo se utiliza en la POO para "referirse a la propiedad por la que es posible enviar mensajes sintácticamente iguales a objetos de tipos distintos"

  • Lo primero que nos debe de llamar la atención al ver este código es que utilizamos dos veces la palabra reservada "abstract". Esta palabra nos indica que la clase "SeleccionFutbol" es una clase abstracta y las clases abstractas no se pueden instanciar, por tanto nunca podremos hacer un "new SeleccionFutbol()". Otra cosa que vemos es que también utilizamos la palabra reservada abstract en un método (en el método entrenamiento). Esto quiere decir que todas las clases hijas de la clase "SeleccionFubol" tienen que tener implementado ese método obligatorio. Por tanto con esto que se acaba de contar y diciendo que la palabra "Polimorfismo" significa "muchas formas", se puede deducir que la clase "SeleccionFutbol" es una clase que puede adoptar diferentes formas y en este ejemplo puede adoptar las formas de "Futbolista", "Entrenador" y "Masajista".
  • Es importante tener en cuenta que utilizamos dos veces la palabra reservada "abstract". Esta palabra nos indica que la clase "SeleccionFutbol" es una clase abstracta y las clases abstractas no se pueden instanciar, por tanto nunca podremos hacer un "new SeleccionFutbol()".
  •  Utilizamos la palabra reservada abstract en un método (en el método entrenamiento). Esto quiere decir que todas las clases hijas de la clase "SeleccionFubol" tienen que tener implementado ese método obligatorio. Por tanto con esto se puede afirmar que la clase "SeleccionFutbol" es una clase que puede adoptar diferentes formas y en este ejemplo puede adoptar las formas de "Futbolista", "Entrenador" y "Masajista".


A nivel de código tendríamos: 

En la clase SeleccionFutbol

package polimorfismo;

public abstract class SeleccionFutbol {
 
 protected int id;
 protected String nombre;
 protected String apellidos;
 protected int edad;
 
 //Geters y Setters
 public int getId() {
  return id;
 }
 public void setId(int id) {
  this.id = id;
 }
 public String getNombre() {
  return nombre;
 }
 public void setNombre(String nombre) {
  this.nombre = nombre;
 }
 public String getApellidos() {
  return apellidos;
 }
 public void setApellidos(String apellidos) {
  this.apellidos = apellidos;
 }
 public int getEdad() {
  return edad;
 }
 public void setEdad(int edad) {
  this.edad = edad;
 }
 
 // Constructor de la clase
 public SeleccionFutbol(int id, String nombre, String apellidos, int edad) {
  super();
  this.id = id;
  this.nombre = nombre;
  this.apellidos = apellidos;
  this.edad = edad;
 }
 //Métodos de la clase
 public void concentrarse() {
  System.out.println("Concentrarse (Clase padre)");
 }
 
 public void viajar() {
  System.out.println("Viajar (Clase Padre)");
 }
 
 // IMPORTANTE -> METODO ABSTRACTO => no se implementa en la clase abstracta pero si en la clases hijas
 public abstract void entrenamiento();

 public void partidoFutbol() {
      System.out.println("Asiste al Partido de Fútbol (Clase Padre)");
 }

}

En la clase Futbolista se tiene

package polimorfismo;

public class Futbolista extends SeleccionFutbol{
 
 //Atributos de la clase Futbolista
 private int dorsal;
 private String demarcacion;
 
 //Getters y Setters
 public int getDorsal() {
  return dorsal;
 }

 public void setDorsal(int dorsal) {
  this.dorsal = dorsal;
 }

 public String getNumero() {
  return demarcacion;
 }

 public void setNumero(String demarcacion) {
  this.demarcacion = demarcacion;
 }
 
 //Constructor de la Clase Futbolista
 public Futbolista(int id, String nombre, String apellidos, int edad, int dorsal, String demarcacion) {
  super(id, nombre, apellidos, edad);
  this.dorsal = dorsal;
  this.demarcacion = demarcacion;
 }
 
 //Métodos propios de la clase Futbolista
  @Override
 public void entrenamiento() {
   System.out.println("Realiza un entrenamiento (Clase Futbolista)");
 }
 
  @Override
 public void partidoFutbol() {
  System.out.println("Juega un partido (Clase Futbolista)");
 }

 public void entrenar() {
  System.out.println("Entrena (Clase Futbolista)");
 }
 
 public void entrevista() {
  System.out.println("Da una Entrevista");
 }

}

En la clase Entrenador:

package polimorfismo;

public class Entrenador extends SeleccionFutbol{

 //Atributos de la clase Entrenador
 private String idFederacion;
 
 //Getters y Setters
 public String getIdFederacion() {
  return idFederacion;
 }

 public void setIdFederacion(String idFederacion) {
  this.idFederacion = idFederacion;
 }

 //Constructor de la Clase Entrenador
 public Entrenador(int id, String nombre, String apellidos, int edad, String idFederacion) {
  super(id, nombre, apellidos, edad);
  this.idFederacion = idFederacion;
 }
 
 //Métodos obligatorios de la clase SeleccionFutbol
 @Override
 public void entrenamiento() {
    System.out.println("Dirige un entrenamiento (Clase Entrenador)");
 }
 
 @Override
 public void partidoFutbol() {
    System.out.println("Dirige un Partido (Clase Entrenador)");
 }

 public void dirigirEntrenamiento() {
  System.out.println("Dirige un entrenamiento");
 }

}

Y para finalizar la actividad se tiene la clase Masajista:

package polimorfismo;

public class Masajista extends SeleccionFutbol{
 
 //Atributos de la clase Masajista
 private String titulacion;
 private int aniosExperiencia;
 
 //Getters y Setters
 public String getTitulacion() {
  return titulacion;
 }

 public void setTitulacion(String titulacion) {
  this.titulacion = titulacion;
 }

 public int getAniosExperiencia() {
  return aniosExperiencia;
 }

 public void setAniosExperiencia(int aniosExperiencia) {
  this.aniosExperiencia = aniosExperiencia;
 }
 
 //Constructor de la clase Masajista
 public Masajista(int id, String nombre, String apellidos, int edad, String titulacion, int aniosExperiencia) {
  super(id, nombre, apellidos, edad);
  this.titulacion = titulacion;
  this.aniosExperiencia = aniosExperiencia; 
 }
 
 //Métodos obligatorios de la clase SeleccionFutbol
 @Override
 public void entrenamiento() {
    System.out.println("Da asistencia en el entrenamiento (Clase Masajista)");
 }
 
 //Métodos de la clase Masajista
 public void darMasaje() {
  System.out.println("Dar masaje");
 }

}


Al ver el código, encontramos que todas las clases hijas tienen implementada el método "entrenamiento()" ya que como dijimos al tenerlo en la clase padre como método abstracto, es obligatorio que todas las clases hijas tengan ese método.

Por otro lado observamos en el código que encima del método "entrenamiento()" y otros métodos, tenemos la etiqueta "@Override". Esta etiqueta sirve para indicar en el código que estamos "re-escribiendo o especializando" un método que se encuentra en la clase padre y que queremos redefinir en la clase hija.

Si observamos esta etiqueta solo está en los métodos de las clases hijas que tenemos definida en la clase padre, por tanto cuando se llame a esos métodos, las clases hijas ejecutaran el método redefinido en la clase hija y las que no lo hayan redefinido se ejecutará es método de la clase padre. Esto es a lo que se llama especialización:



Abstracción

En Java, abstracción se usa cuando tenemos métodos o propiedades que se repiten en muchas clases que por lo general tienen algo en común. Abstracción al igual que interfaces no pueden ser inicializadas o no se puede crear un objeto a través de ellas. A pesar de esa igualdad abstracción e interfaz tienen muchas diferencias. Es importante saber que una clase abstracta se tiene que heredar y no implementar


Veamos un ejemplo de cómo luce una clase abstracta en Java para tener una mejor idea.

public abstract class MiClaseAbstracta {
 
    // una propiedad normal como en cualquier clase
    private int propiedad;
 
    // una constante
    public static final int CONSTANTE = 1;
 
    // un metodo normal como en cualquier clase
    protected int sumar(int argumento1, int argumento2) {
         return argumento1 + argumento2;
    }
 
    // un metodo abstracto que tiene que ser
    // implementado por la clase que herede esta
    // clase abstracta.
    public abstract int restar(int argumento1, int argumento2);
}

Como se puede ver se utiliza la palabra clave "abstract" para definir la clase como abstracta. También podemos definir métodos con implementación y abstractos como se pudo ver en el código anterior

Ahora en el siguiente código vamos a visualizar como luce una clase la cual extiende de la clase abstracta que se creo anteriormente:

public class MiClase extends MiClaseAbstracta {
 
    @Override
    public int restar(int argumento1, int argumento2) {
        return argumento1 - argumento2;
    }
 
    // Como sumar tiene modificador de acceso "protected"
    // solo puede ser accedido por una clase que lo hereda.
    // por eso creamos una clase public que internamente
    // llama al metodo protected de la clase publica.
    public int sumar(int argumento1, int argumento2) {
 
        // para llamar al metodo de la clase padre
        // usamos la palabra clave "super".
        return super.sumar(argumento1, argumento2);
    }
}
Como podemos ver en el código anterior cuando definimos la clase utilizamos la palabra "extends" para que esta herede de la clase abstracta que creamos anteriormente. Por esta razón tenemos que tener muy presente que solo podemos heredar de una clase abstracta

Métodos Abstractos:
A su vez, las clases abstractas suelen contener métodos abstractos. Para que un método se considere abstracto ha de incluir en su signatura la palabra clave abstract. Además un método abstracto tiene estas peculiaridades:

  • No tiene cuerpo (llaves): sólo consta de signatura con paréntesis.
  • Su signatura termina con un punto y coma.
  • Sólo puede existir dentro de una clase abstracta. De esta forma se evita que haya métodos que no se puedan ejecutar dentro de clases concretas. Visto de otra manera, si una clase incluye un método abstracto, forzosamente la clase será una clase abstracta.
  • Los métodos abstractos forzosamente habrán de estar sobrescritos en las subclases. Si una subclase no implementa un método abstracto de la superclase tiene un método no ejecutable, lo que la fuerza a ser una subclase abstracta. Para que la subclase sea concreta habrá de implementar métodos sobrescritos para todos los métodos abstractos de sus superclases.
  • Un método abstracto para Java es un método que nunca va a ser ejecutado porque no tiene cuerpo. Simplemente, un método abstracto referencia a otros métodos de las subclases. Podemos ver que la utilidad que tiene un método abstracto es como una palanca que fuerza dos cosas:
                            1. No se puedan crear objetos de una clase.
                            2. Todas las subclases sobrescriban el método declarado como abstracto.
Nota: Debemos tener en cuenta que una clase puede ser declarada como abstracta y no contener métodos abstractos. En algunos casos la clase abstracta simplemente sirve para efectuar operaciones comunes a subclases sin necesidad de métodos abstractos.

Tengamos como referencia el código anterior, como podemos ver en la clase "MiClaseAbstracta" posee un método abstracto

public abstract int restar(int argumento1, int argumento2);

Según como hemos venido diciendo el método abstracto creado tiene una estructura simple en el cual solo se define su tipo (int, String, float, etc.) y sus argumentos. Cuando se quiera realizar la lógica del método esto se realiza en una clase sobrescribiendo su estructura como lo vemos en su clase hija MiClase.

@Override
    public int restar(int argumento1, int argumento2) {
        return argumento1 - argumento2;
    }

Para complementar lo que hemos visto de las clases abstractas vamos a seguir el siguiente ejemplo practico



Última modificación: miércoles, 16 de marzo de 2022, 09:43