Java es un lenguaje de programación orientado a objetos (OOP) basado en clases que se basa en el concepto de objetos. Los conceptos OOP (OOP) pretenden mejorar la legibilidad y reutilización del código al definir cómo estructurar un programa Java de manera eficiente. Los principios fundamentales de la programación orientada a objetos son:
- Abstracción
- Encapsulacion
- Herencia
- Polimorfismo
- Asociación
- Agregación
- Composición
Java viene con estructuras de código específicas para cada principio OOP. Por ejemplo, la
extends
palabra clave para los métodos de herencia o getter y setter para la encapsulación.¿Qué son los conceptos de POO en Java?
Los conceptos OOP nos permiten crear interacciones específicas entre objetos Java. Permiten reutilizar el código sin crear riesgos de seguridad o hacer que un programa Java sea menos legible.
Aquí están los cuatro principios principales en más detalle.
Abstracción
La abstracción tiene como objetivo ocultar la complejidad de los usuarios y mostrarles solo la información relevante. Por ejemplo, si desea conducir un automóvil, no necesita conocer su funcionamiento interno. Lo mismo ocurre con las clases de Java. Puede ocultar los detalles de la implementación interna utilizando clases abstractas o interfaces. En el nivel abstracto, solo necesita definir las firmas del método (nombre y lista de parámetros) y dejar que cada clase las implemente a su manera.
Abstracción en Java:
- Oculta la complejidad subyacente de los datos.
- Ayuda a evitar el código repetitivo.
- Presenta únicamente la firma de funcionalidad interna.
- Da flexibilidad a los programadores para cambiar la implementación del comportamiento abstracto.
- La abstracción parcial (0-100%) se puede lograr con clases abstractas
- La abstracción total (100%) se puede lograr con interfaces
Encapsulacion
La encapsulación nos permite proteger los datos almacenados en una clase del acceso a todo el sistema. Como su nombre lo indica, protege los contenidos internos de una clase como una cápsula de la vida real. Puede implementar la encapsulación en Java manteniendo los campos (variables de clase) privados y proporcionando métodos públicos de obtención y establecimiento para cada uno de ellos. Java Beans son ejemplos de clases totalmente encapsuladas.
Encapsulación en Java:
- Restringe el acceso directo a los miembros de datos (campos) de una clase.
- Los campos se establecen en privado
- Cada campo tiene un método getter y setter.
- Métodos de Getter devuelven el campo
- Los métodos de Setter nos permiten cambiar el valor del campo.
Polimorfismo
[El polimorfismo ( https://en.wikipedia.org/wiki/Polymorphism) se refiere a la capacidad de realizar una determinada acción de diferentes maneras. En Java, el polimorfismo puede tomar dos formas: sobrecarga de métodos y anulación de métodos. La sobrecarga de métodos ocurre cuando varios métodos con el mismo nombre están presentes en una clase. Cuando se llaman, se diferencian por el número, orden y tipos de sus parámetros. La anulación del método se produce cuando la clase secundaria anula un método de su padre.
Polimorfismo en Java:
- El mismo nombre de método se usa varias veces.
- Se pueden llamar diferentes métodos del mismo nombre desde el objeto.
- Todos los objetos Java pueden considerarse polimórficos (como mínimo, son de su propio tipo e instancias de la clase Objeto).
- Un ejemplo de polimorfismo estático en Java es la sobrecarga de métodos.
- Ejemplo de polimorfismo dinámico en Java es el método de anulación.
Herencia
La herencia hace posible crear una clase secundaria que hereda los campos y métodos de la clase principal. La clase secundaria puede anular los valores y métodos de la clase principal, sin embargo, no es necesario. También puede agregar nuevos datos y funcionalidad a su padre. Las clases principales también se denominan superclases o clases básicas, mientras que las clases secundarias también se conocen como subclases o clases derivadas. Java usa la
extends
palabra clave para implementar el principio de herencia en el código.Herencia en Java:
- Una clase (clase secundaria) puede extender otra clase (clase primaria) heredando sus características.
- Implementa el principio de programación DRY (Don't Repeat Yourself).
- Mejora la reutilización del código.
- La herencia multinivel está permitida en Java (una clase secundaria también puede tener su propia clase secundaria).
- No se permiten múltiples herencias en Java (una clase no puede extender más de una clase).
Asociación
Además de los cuatro principios principales de OOP, Java también trabaja con otros tres conceptos (asociación, agregación, composición) que puede utilizar al diseñar sus programas. La agregaciónes una forma especial de asociación , mientras que la composición es una forma especial de agregación .
Asociación simplemente significa el acto de establecer una relación entre dos clases no relacionadas. Por ejemplo, cuando declara dos campos de diferentes tipos (por ejemplo,
Car
y Bicycle
) dentro de la misma clase y los hace interactuar entre sí, ha realizado la asociación.Asociación en Java:
- Dos clases separadas están asociadas a través de sus objetos.
- Las dos clases no están relacionadas, cada una puede existir sin la otra.
- Puede ser una relación de uno a uno, de uno a muchos, de muchos a uno o de muchos a muchos.
Agregación
La agregación es un tipo más estrecho de asociación. Ocurre cuando hay una relación unidireccional (HAS-A) entre las dos clases que asocia a través de sus objetos. Por ejemplo, todo
Passenger
tiene un Car
pero un Car
no tiene necesariamente un Passenger
. Cuando declara la Passenger
clase, puede crear un campo del Car
tipo que muestre a qué automóvil pertenece el pasajero. Luego, cuando crea una instancia de un nuevo Passenger
objeto, también puede acceder a los datos almacenados en el relacionado Car
.Agregación en Java:
- Asociación unidireccional.
- Representa una relación HAS-A entre dos clases.
- Sólo una clase depende de la otra.
Composición
La composición es una forma más estricta de agregación. Ocurre cuando las dos clases que asocia son mutuamente dependientes unas de otras y no pueden existir una sin la otra. Por ejemplo, tomar una
Car
y una Engine
clase. A Car
no se puede ejecutar sin Engine
, mientras que Engine
tampoco puede funcionar sin estar integrado en a Car
. Este tipo de relación entre objetos también se llama una relación PARTE-DE.Composición en Java:
- Una forma restringida de agregación.
- Representa una relación PART-OF entre dos clases
- Ambas clases dependen unas de otras
- Si una clase deja de existir, la otra no puede sobrevivir sola
Conceptos de OOP en la infografía de Java
Usa esta infografía en tu blog.¿Cuáles son las características de la POO?
Ahora, veamos las características de la vida real de los cuatro conceptos principales de POO en Java: abstracción, encapsulación, herencia y polimorfismo.
Abstracción
Con la abstracción, puede ocultar el funcionamiento interno de un objeto y solo mostrar las características que el usuario necesita conocer. Java proporciona dos formas de implementar la abstracción: clases abstractas e interfaces. Con las clases abstractas, puede lograr una abstracción parcial, mientras que las interfaces hacen posible la abstracción total (100%).
Clases abstractas
Una clase abstracta es una superclase (clase principal) que no puede ser instanciada. Debe crear una instancia de una de sus clases secundarias si desea crear un nuevo objeto. Las clases abstractas pueden tener métodos tanto abstractos como concretos. Los métodos abstractos contienen solo la firma del método, mientras que los métodos concretos también declaran un cuerpo del método. Las clases abstractas se definen con la
abstract
palabra clave.En el siguiente ejemplo, puede ver una clase abstracta llamada
Animal
con dos métodos abstractos y uno concreto.abstract class Animal {
// abstract methods
abstract void move();
abstract void eat();
// concrete method
void label() {
System.out.println("Animal's data:");
}
}
Amplíe la
Animal
clase abstracta con dos clases secundarias: Bird
y Fish
. Ambos establecieron su propia funcionalidad para las move()
y eat()
abstractos métodos.class Bird extends Animal {
void move() {
System.out.println("Moves by flying.");
}
void eat() {
System.out.println("Eats birdfood.");
}
}
class Fish extends Animal {
void move() {
System.out.println("Moves by swimming.");
}
void eat() {
System.out.println("Eats seafood.");
}
}
Ahora, pruébalo con las clases
TestBird
y TestFish
. Ambos llaman al método concreto ( label()
) y los dos métodos abstractos ( move()
y eat()
).class TestBird {
public static void main(String[] args) {
Animal myBird = new Bird();
myBird.label();
myBird.move();
myBird.eat();
}
}
class TestFish {
public static void main(String[] args) {
Animal myFish = new Fish();
myFish.label();
myFish.move();
myFish.eat();
}
}
En la consola, el método concreto ha sido llamado desde la
Animal
clase abstracta, mientras que los dos métodos abstractos han sido llamados desde Bird()
y Fish()
, respectivamente.[Console output of TestBird]
Animal's data:
Moves by flying.
Eats birdfood.
[Console output of TestFish]
Animal's data:
Moves by swimming.
Eats seafood.
Interfaces
Una interfaz es una clase 100% abstracta. Solo puede tener campos estáticos, finales, públicos y métodos abstractos. Con frecuencia, también se lo denomina modelo de una clase. Las interfaces de Java nos permiten implementar múltiples herencias en nuestro código, ya que una clase puede implementar cualquier número de interfaces. Las clases pueden acceder a una interfaz usando la
implements
palabra clave.En el ejemplo, defina dos interfaces,
Animal
y Bird
. Animal
tiene dos métodos abstractos, mientras que Bird
tiene dos campos estáticos y un método abstracto.interface Animal {
public void eat();
public void sound();
}
interface Bird {
int numberOfLegs = 2;
String outerCovering = "feather";
public void fly();
}
La clase
Eagle
implementa ambas interfaces. Define su propia funcionalidad para los tres métodos abstractos. Los eat()
y los sound()
métodos provienen de la Animal
clase, mientras que fly()
viene de Bird
.class Eagle implements Animal, Bird {
public void eat() {
System.out.println("Eats reptiles and amphibians.");
}
public void sound() {
System.out.println("Has a high-pitched whistling sound.");
}
public void fly() {
System.out.println("Flies up to 10,000 feet.");
}
}
En la
TestEagle
clase de prueba, cree una instancia de un nuevo Eagle
objeto (llamado myEagle
) e imprima todos los campos y métodos en la consola.Como los campos estáticos no pertenecen a un objeto específico sino a toda una clase, debe acceder a ellos desde la
Bird
interfaz en lugar del myEagle
objeto.class TestEagle {
public static void main(String[] args) {
Eagle myEagle = new Eagle();
myEagle.eat();
myEagle.sound();
myEagle.fly();
System.out.println("Number of legs: " + Bird.numberOfLegs);
System.out.println("Outer covering: " + Bird.outerCovering);
}
}
La consola de Java devuelve toda la información a la que desea acceder:
[Console output of TestEagle]
Eats reptiles and amphibians.
Has a high-pitched whistling sound.
Flies up to 10,000 feet.
Number of legs: 2
Outer covering: feather
Encapsulacion
Con la encapsulación, puede proteger los campos de una clase. Para hacerlo, declare los campos como privados y proporcione acceso a ellos con los métodos de obtención y establecimiento.
La
Animal
siguiente clase está completamente encapsulada. Tiene tres campos privados y cada uno de ellos tiene su propio conjunto de métodos de obtención y configuración.class Animal {
private String name;
private double averageWeight;
private int numberOfLegs;
// Getter methods
public String getName() {
return name;
}
public double getAverageWeight() {
return averageWeight;
}
public int getNumberOfLegs() {
return numberOfLegs;
}
// Setter methods
public void setName(String name) {
this.name = name;
}
public void setAverageWeight(double averageWeight) {
this.averageWeight = averageWeight;
}
public void setNumberOfLegs(int numberOfLegs) {
this.numberOfLegs = numberOfLegs;
}
}
TestAnimal
clase primero establece un valor para cada campo con los métodos de establecimiento, luego imprime los valores usando los métodos de obtención.public class TestAnimal {
public static void main(String[] args) {
Animal myAnimal = new Animal();
myAnimal.setName("Eagle");
myAnimal.setAverageWeight(1.5);
myAnimal.setNumberOfLegs(2);
System.out.println("Name: " + myAnimal.getName());
System.out.println("Average weight: " + myAnimal.getAverageWeight() + "kg");
System.out.println("Number of legs: " + myAnimal.getNumberOfLegs());
}
}
Como puede ver a continuación, la consola de Java devuelve correctamente todos los valores que configuró con los métodos de establecimiento:
[Console output of TestAnimal]
Name: Eagle
Average weight: 1.5kg
Number of legs: 2
Herencia
La herencia nos permite extender una clase con clases secundarias que heredan los campos y métodos de la clase principal. Es una excelente manera de lograr la reutilización del código. En Java, necesitamos usar la
extends
palabra clave para crear una clase secundaria.En el ejemplo, la
Eagle
clase extiende la Bird
clase padre. Hereda todos sus campos y métodos, y define dos campos adicionales que pertenecen solo a Eagle
.class Bird {
public String reproduction = "egg";
public String outerCovering = "feather";
public void flyUp() {
System.out.println("Flying up...");
}
public void flyDown() {
System.out.println("Flying down...");
}
}
class Eagle extends Bird {
public String name = "eagle";
public int lifespan = 15;
}
La
TestEagle
clase crea una instancia de un nuevo Eagle
objeto e imprime toda la información (tanto los campos y métodos heredados como los dos campos adicionales definidos en la Eagle
clase).class TestEagle {
public static void main(String[] args) {
Eagle myEagle = new Eagle();
System.out.println("Name: " + myEagle.name); System.out.println("Reproduction: " + myEagle.reproduction);
System.out.println("Outer covering: " + myEagle.outerCovering);
System.out.println("Lifespan: " + myEagle.lifespan);
myEagle.flyUp();
myEagle.flyDown();
}
}
Puedes ver la salida de la consola a continuación:
[Console output of TestEagle]
Reproduction: another egg
Outer covering: feather
Lifespan: 15
Flying up...
Flying down...
Polimorfismo
El polimorfismo hace posible utilizar la misma entidad en diferentes formas. En Java, esto significa que puede declarar varios métodos con el mismo nombre hasta que sean diferentes en ciertas características. Java nos proporciona dos formas de implementar el polimorfismo: la sobrecarga de métodos y la cancelación de métodos.
Polimorfismo estático
La sobrecarga de métodos significa que puede tener varios métodos con el mismo nombre dentro de una clase. Sin embargo, el número, los nombres o los tipos de sus parámetros deben ser diferentes.
Por ejemplo, la
Bird()
siguiente clase tiene tres fly()
métodos. El primero no tiene ningún parámetro, el segundo tiene un parámetro ( height
) y el tercero tiene dos parámetros ( name
y height
).class Bird {
public void fly() {
System.out.println("The bird is flying.");
}
public void fly(int height) {
System.out.println("The bird is flying " + height + " feet high.");
}
public void fly(String name, int height) {
System.out.println("The " + name + " is flying " + height + " feet high.");
}
}
La clase de prueba crea una instancia de un nuevo
Bird
objeto y llama al fly()
método tres veces. En primer lugar, sin parámetros, en segundo lugar, con un parámetro entero para height
, y en tercer lugar, con dos parámetros para name
y height
.class TestBird {
public static void main(String[] args) {
Bird myBird = new Bird();
myBird.fly();
myBird.fly(10000);
myBird.fly("eagle", 10000);
}
}
En la consola, podemos ver que Java podría haber diferenciado los tres
fly()
métodos polimórficos :[Console output of TestBird]
The bird is flying.
The bird is flying 10000 feet high.
The eagle is flying 10000 feet high.
Polimorfismo dinámico
Al utilizar la función de anulación de métodos de Java, puede anular los métodos de una clase principal de su clase secundaria.
La
Bird
clase extiende la Animal
clase en el siguiente ejemplo. Ambos tienen un eat()
método. Por defecto, Bird
hereda el eat()
método de su padre . Sin embargo, como también define su propio eat()
método, Java anulará el método original y llamará eat()
desde la clase secundaria.class Animal {
public void eat() {
System.out.println("This animal eats insects.");
}
}
class Bird extends Animal {
public void eat() {
System.out.println("This bird eats seeds.");
}
}
La
TestBird
clase primero crea una instancia de un nuevo Animal
objeto y llama a su eat()
método. Luego, también crea un Bird
objeto y eat()
vuelve a llamar al método polimórfico .class TestBird {
public static void main(String[] args) {
Animal myAnimal = new Animal();
myAnimal.eat();
Bird myBird = new Bird();
myBird.eat();
}
}
La consola devuelve correctamente los valores de los métodos relevantes. Por lo tanto, Java podría haber diferenciado los dos
eat()
métodos de hecho.[Console output of TestBird]
This animal eats insects.
This bird eats seeds.
Conclusión
Los conceptos de OOP en Java definen cómo estructurar un problema de Java de manera más eficiente.
0 Comentarios