En este laboratorio, aprenderá sobre modificadores de acceso y herencia. Con diferentes modificadores, los niveles de acceso son diferentes. La herencia en Java es como la herencia biológica en el sentido de que los hijos pueden conservar las características de los padres y comportarse de manera diferente en algunos aspectos.
Skills Graph
%%%%{init: {'theme':'neutral'}}%%%%
flowchart RL
java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"])
java/ObjectOrientedandAdvancedConceptsGroup -.-> java/classes_objects("Classes/Objects")
java/ObjectOrientedandAdvancedConceptsGroup -.-> java/class_attributes("Class Attributes")
java/ObjectOrientedandAdvancedConceptsGroup -.-> java/class_methods("Class Methods")
java/ObjectOrientedandAdvancedConceptsGroup -.-> java/constructors("Constructors")
java/ObjectOrientedandAdvancedConceptsGroup -.-> java/modifiers("Modifiers")
java/ObjectOrientedandAdvancedConceptsGroup -.-> java/inheritance("Inheritance")
subgraph Lab Skills
java/classes_objects -.-> lab-178543{{"Modificadores de Acceso y Herencia"}}
java/class_attributes -.-> lab-178543{{"Modificadores de Acceso y Herencia"}}
java/class_methods -.-> lab-178543{{"Modificadores de Acceso y Herencia"}}
java/constructors -.-> lab-178543{{"Modificadores de Acceso y Herencia"}}
java/modifiers -.-> lab-178543{{"Modificadores de Acceso y Herencia"}}
java/inheritance -.-> lab-178543{{"Modificadores de Acceso y Herencia"}}
end
Modificadores de Acceso
Hasta ahora, ya hemos escrito un poco de código. En el laboratorio anterior, escribimos una clase. Hay algunos modificadores como public y private. Entonces, ¿qué significan estas palabras?
Java proporciona una serie de modificadores de acceso para establecer los niveles de acceso de clases, variables, métodos y constructores. Los cuatro niveles de acceso son:
predeterminado: Visible dentro del paquete, el predeterminado. No se necesitan modificadores.
privado: Solo visible para la clase que lo define.
público: Visible en todo el Universo Java (todos los tipos). Puedes acceder a ellos en cualquier lugar.
protegido: Visible para el paquete y todas las subclases (incluso aquellas en otros paquetes).
Java proporciona una serie de modificadores no de acceso para lograr muchas otras maneras de ajustar finamente el comportamiento:
estático: Este modificador se utiliza para crear variables o métodos que existirán independientemente de cualquier instancia de la clase. Solo existe una copia de la variable estática para la clase, independientemente del número de instancias creadas.
final: Una variable final solo se puede inicializar explícitamente una vez. Un método final no se puede sobrescribir por ninguna subclase. Una clase se declara como final para evitar que la clase sea heredada.
abstracto: Una clase abstracta nunca se puede instanciar. Un método abstracto es un método declarado sin ninguna implementación.
sincronizado/volátil: Los modificadores sincronizado y volátil se utilizan en relación con los hilos.
Ejemplo:
Escribe el siguiente código en el archivo /home/labex/project/modifierTest.java:
public class modifierTest {
// Las variables estáticas se inicializan cuando se carga la clase.
public static int i = 10;
public static final int NUM = 5;
// Las variables no estáticas se inicializan cuando se crea el objeto.
public int j = 1;
/*
* Bloque de código estático aquí, esto se ejecutará cuando se cargue la clase
* crear un nuevo objeto no ejecutará el bloque nuevamente, solo se ejecuta una vez.
*/
static{
System.out.println("this is a class static block.");
}
public static void main(String[] args)
{
System.out.println("this is in main method");
// Puedes acceder a i y cambiarlo
modifierTest.i = 20; // Lo mismo que obj.i = 20
System.out.println("Class variable i = " + modifierTest.i);
// Puedes acceder a NUM, pero no puedes cambiarlo
// HelloWorld.NUM = 10; Esto causará un error, NUM es final, es inmutable
System.out.println("Class variable NUM = " + modifierTest.NUM);
// Crea un nuevo objeto
modifierTest obj = new modifierTest();
// Podemos usar tanto la clase como el objeto para acceder a métodos y propiedades estáticas
obj.staticMethod(); // Lo mismo que modifierTest.staticMethod()
// No puedes acceder a j de esta manera: modifierTest.j
System.out.println("Object variable j = " + obj.j);
}
// El constructor, solo se llamará cuando se cree un nuevo objeto.
public modifierTest(){
System.out.println("this is in object's constructor.");
}
public static void staticMethod(){
System.out.println("this is a static method");
}
}
Salida:
Ejecuta el archivo modifierTest.java utilizando los siguientes comandos:
this is a class static block.
this is in main method
Class variable i = 20
Class variable NUM = 5
this is in object's constructor.
this is a static method
Object variable j = 1
Herencia
En muchos casos, hemos escrito una clase. Y luego, necesitamos escribir una nueva clase solo para modificar un poco del código de la clase anterior, y tienen alguna relación lógica. Aquí podemos usar la herencia. Usamos la palabra clave extends para implementar la herencia. Las subclases heredan todas las propiedades y métodos accesibles de la superclase, y las subclases también pueden tener las suyas propias especiales. En las subclases, podemos acceder a las que se declaran en la superclase como public o protected, pero las private no podemos acceder a ellas directamente. Veamos un ejemplo: La estructura de herencia se muestra como la imagen. Puedes implementar herencia jerárquica (vertical) o herencia múltiple (horizontal):
Ejemplo:
Escribe el siguiente código en el archivo /home/labex/project/inheritanceTest.java:
class Animal{
// De qué tipo de animal soy.
private String species;
private int age = 8;
public Animal(){
System.out.println("Constructor de Animal");
}
public void grow(){
// En esta clase, podemos acceder directamente a las propiedades privadas.
System.out.println("Tengo " + this.age + " años, estoy creciendo.");
}
}
class Dog extends Animal{
private String color;
// En esta clase, no podemos acceder a los atributos privados de la superclase, pero grow() está bien.
public Dog(){
System.out.println("Constructor de Dog");
}
public void run(){
this.grow();
System.out.println("Soy un perro, puedo correr.");
}
}
class Bird extends Animal{
private double weight;
public Bird(){
// Si invocas explícitamente el constructor de la superclase, debe estar en la primera línea aquí.
// super();
System.out.println("Constructor de Bird");
}
public void fly(){
this.grow();
System.out.println("Soy un pájaro, puedo volar.");
}
}
public class inheritanceTest{
public static void main(String[] args){
Dog dog = new Dog();
dog.run();
Bird bird = new Bird();
bird.fly();
}
}
Salida:
Ejecuta el archivo inheritanceTest.java utilizando los siguientes comandos:
Constructor de Animal
Constructor de Dog
Tengo 8 años, estoy creciendo.
Soy un perro, puedo correr.
Constructor de Animal
Constructor de Bird
Tengo 8 años, estoy creciendo.
Soy un pájaro, puedo volar.
Cuando veas esta salida, es posible que te confundas. No te preocupes; te explicaré por qué. Cuando creamos un objeto de una subclase usando new, por defecto primero invoca el constructor predeterminado de la superclase desde la estructura de árbol de herencia "de arriba hacia abajo" y por último ejecuta su propio constructor. El constructor de la superclase se puede llamar explícitamente usando la palabra clave super, pero debe ser la primera declaración en un constructor si está presente. La palabra clave super se refiere a la superclase, inmediatamente encima de la clase que llama en la jerarquía.
Resumen
Con los modificadores de acceso, podemos escribir código seguro, ocultar detalles y lograr el control de acceso. Otros usuarios no necesitan saber cómo implementamos los detalles de los métodos. Les proporcionamos una interfaz a otros invocadores. Para los modificadores de acceso, puede leer las bibliotecas de código fuente de Java para entender cuál es la diferencia. La herencia, recuerde la estructura jerárquica, es la relación entre clases.