Buscar..


Introducción

Los objetos tienen estados y comportamientos. Ejemplo: Un perro tiene estados (color, nombre, raza y comportamientos): menear la cola, ladrar, comer. Un objeto es una instancia de una clase.

Clase: una clase se puede definir como una plantilla / modelo que describe el comportamiento / estado que admite el objeto de su tipo.

Sintaxis

  • clase Ejemplo {} // clase palabra clave, nombre, cuerpo

Clase posible más simple

class TrivialClass {}

Una clase consta de un mínimo de la palabra clave de class , un nombre y un cuerpo, que pueden estar vacíos.

Se crea una instancia de una clase con el new operador.

TrivialClass tc = new TrivialClass();

Miembro Objeto vs Miembro Estático

Con esta clase:

class ObjectMemberVsStaticMember {

    static int staticCounter = 0;
    int memberCounter = 0;

    void increment() {
        staticCounter ++;
        memberCounter++;
    }
}

el siguiente fragmento de código:

final ObjectMemberVsStaticMember o1 = new ObjectMemberVsStaticMember();
final ObjectMemberVsStaticMember o2 = new ObjectMemberVsStaticMember();

o1.increment();

o2.increment();
o2.increment();

System.out.println("o1 static counter " + o1.staticCounter);
System.out.println("o1 member counter " + o1.memberCounter);
System.out.println();

System.out.println("o2 static counter " + o2.staticCounter);
System.out.println("o2 member counter " + o2.memberCounter);
System.out.println();

System.out.println("ObjectMemberVsStaticMember.staticCounter = " + ObjectMemberVsStaticMember.staticCounter);

// the following line does not compile. You need an object
// to access its members
//System.out.println("ObjectMemberVsStaticMember.staticCounter = " + ObjectMemberVsStaticMember.memberCounter);

produce esta salida:

o1 static counter 3
o1 member counter 1

o2 static counter 3
o2 member counter 2

ObjectMemberVsStaticMember.staticCounter = 3

Nota: No debe llamar a miembros static en objetos, sino en clases. Si bien no hace una diferencia para la JVM, los lectores humanos lo apreciarán.

static miembros static son parte de la clase y existen solo una vez por clase. Los miembros no static existen en las instancias, hay una copia independiente para cada instancia. Esto también significa que necesita acceder a un objeto de esa clase para acceder a sus miembros.

Métodos de sobrecarga

A veces, se debe escribir la misma funcionalidad para diferentes tipos de entradas. En ese momento, uno puede usar el mismo nombre de método con un conjunto diferente de parámetros. Cada conjunto diferente de parámetros se conoce como una firma de método. Como se ve en el ejemplo, un solo método puede tener varias firmas.

public class Displayer {

    public void displayName(String firstName) {
        System.out.println("Name is: " + firstName);
    }

    public void displayName(String firstName, String lastName) {
        System.out.println("Name is: " + firstName + " " + lastName);
    }

    public static void main(String[] args) {
        Displayer displayer = new Displayer();
        displayer.displayName("Ram");          //prints "Name is: Ram"
        displayer.displayName("Jon", "Skeet"); //prints "Name is: Jon Skeet"
    }
}

La ventaja es que se llama a la misma funcionalidad con dos números diferentes de entradas. Al invocar el método de acuerdo con la entrada que estamos pasando, (en este caso, un valor de cadena o dos valores de cadena) se ejecuta el método correspondiente.

Los métodos pueden ser sobrecargados:

  1. Basado en el número de parámetros pasados.

    Ejemplo: method(String s) y method(String s1, String s2) .

  1. Basado en el orden de los parámetros .

    Ejemplo: method(int i, float f) y method(float f, int i)) .

Nota: los métodos no pueden sobrecargarse cambiando solo el tipo de retorno ( int method() se considera el mismo que String method() y lanzará una RuntimeException si se intenta). Si cambia el tipo de retorno, también debe cambiar los parámetros para sobrecargar.

Construcción y uso de objetos básicos

Los objetos vienen en su propia clase, por lo que un ejemplo simple sería un automóvil (explicaciones detalladas a continuación):

public class Car {
    
    //Variables describing the characteristics of an individual car, varies per  object
   private int milesPerGallon;
   private String name;
   private String color;
   public int numGallonsInTank; 
    
    public Car(){
        milesPerGallon = 0;
        name = "";
        color = "";
        numGallonsInTank = 0;
    }
    
    //this is where an individual object is created
    public Car(int mpg, int, gallonsInTank, String carName, String carColor){
        milesPerGallon = mpg;
        name = carName;
        color = carColor;
        numGallonsInTank = gallonsInTank;
    }

    //methods to make the object more usable

    //Cars need to drive
    public void drive(int distanceInMiles){
        //get miles left in car
        int miles = numGallonsInTank * milesPerGallon;
        
        //check that car has enough gas to drive distanceInMiles
        if (miles <= distanceInMiles){
            numGallonsInTank = numGallonsInTank - (distanceInMiles / milesPerGallon)
            System.out.println("Drove " + numGallonsInTank + " miles!");
        } else {
            System.out.println("Could not drive!");
        }
    }

    public void paintCar(String newColor){
        color = newColor;
    }
        //set new Miles Per Gallon
    public void setMPG(int newMPG){
        milesPerGallon = newMPG;
    }

       //set new number of Gallon In Tank
    public void setGallonsInTank(int numGallons){
        numGallonsInTank = numGallons;
    }
    
    public void nameCar(String newName){
        name = newName;
    }

    //Get the Car color
    public String getColor(){
        return color;
    }

    //Get the Car name
    public String getName(){
        return name;
    }

    //Get the number of Gallons
    public String getGallons(){
        return numGallonsInTank;
    }
    
}  

Los objetos son instancias de su clase. Entonces, la forma en que crearía un objeto sería llamando a la clase Car de una de las dos formas en su clase principal (método principal en Java u onCreate en Android).

Opción 1

`Car newCar = new Car(30, 10, "Ferrari", "Red");

La opción 1 es donde esencialmente le dice al programa todo sobre el Coche al crear el objeto. Cambiar cualquier propiedad del automóvil requeriría llamar a uno de los métodos, como el método repaintCar . Ejemplo:

 newCar.repaintCar("Blue");

Nota: asegúrese de pasar el tipo de datos correcto al método. En el ejemplo anterior, también puede pasar una variable al método repaintCar siempre que el tipo de datos sea correcto .

Ese fue un ejemplo de cambio de propiedades de un objeto, recibir propiedades de un objeto requeriría el uso de un método de la clase Car que tenga un valor de retorno (es decir, un método que no sea void ). Ejemplo:

String myCarName = newCar.getName();  //returns string "Ferrari"

La opción 1 es la mejor opción cuando tiene todos los datos del objeto en el momento de la creación.

opcion 2

`Car newCar = new Car();

La opción 2 obtiene el mismo efecto pero requiere más trabajo para crear un objeto correctamente. Quiero recordar a este Constructor en la clase de Automóviles:

public void Car(){
        milesPerGallon = 0;
        name = "";
        color = "";
        numGallonsInTank = 0;
    }

Tenga en cuenta que no tiene que pasar ningún parámetro al objeto para crearlo. Esto es muy útil para cuando no tiene todos los aspectos del objeto pero necesita usar las partes que tiene. Esto establece datos genéricos en cada una de las variables de instancia del objeto, de modo que, si solicita un dato que no existe, no se generan errores.

Nota: No olvide que debe configurar las partes del objeto más adelante con las que no lo haya inicializado. Por ejemplo,

Car myCar = new Car();
String color = Car.getColor(); //returns empty string

Este es un error común entre los objetos que no están inicializados con todos sus datos. Se evitaron los errores porque hay un Constructor que permite que se cree un objeto de Coche vacío con variables de apoyo ( public Car(){} ), pero ninguna parte de myCar fue realmente personalizada. Ejemplo correcto de crear un objeto de coche:

Car myCar = new Car();
myCar.nameCar("Ferrari");
myCar.paintCar("Purple");
myCar.setGallonsInTank(10);
myCar.setMPG(30);

Y, como recordatorio, obtenga las propiedades de un objeto llamando a un método en su clase principal. Ejemplo:

String myCarName = myCar.getName(); //returns string "Ferrari"

Constructores

Los constructores son métodos especiales nombrados después de la clase y sin un tipo de retorno, y se utilizan para construir objetos. Los constructores, como los métodos, pueden tomar parámetros de entrada. Los constructores se utilizan para inicializar objetos. Las clases abstractas también pueden tener constructores.

public class Hello{
    // constructor
    public Hello(String wordToPrint){
        printHello(wordToPrint);
    }
    public void printHello(String word){
        System.out.println(word);
    }
}
// instantiates the object during creating and prints out the content
// of wordToPrint

Es importante entender que los constructores son diferentes de los métodos de varias maneras:

  1. Los constructores solo pueden tomar los modificadores public , private y protected , y no pueden ser declarados abstract , final , static o synchronized .

  2. Los constructores no tienen un tipo de retorno.

  3. Los constructores DEBEN tener el mismo nombre que el nombre de la clase. En el ejemplo de Hello , el nombre del constructor del objeto Hello es el mismo que el nombre de la clase.

  4. La palabra clave this tiene un uso adicional dentro de los constructores. this.method(...) llama a un método en la instancia actual, mientras que this(...) refiere a otro constructor en la clase actual con diferentes firmas.

A los constructores también se les puede llamar por herencia usando la palabra clave super .

public class SuperManClass{

    public SuperManClass(){
        // some implementation
    }
    
    // ... methods
}


public class BatmanClass extends SupermanClass{
    public BatmanClass(){
        super();
    }
    //... methods...
}

Ver la especificación del lenguaje Java # 8.8 y # 15.9

Inicializando campos finales estáticos usando un inicializador estático

Para inicializar campos static final que requieren el uso de más de una expresión, se puede usar un inicializador static para asignar el valor. El siguiente ejemplo inicializa un conjunto no modificable de String s:

public class MyClass {

    public static final Set<String> WORDS;
    
    static {
        Set<String> set = new HashSet<>();
        set.add("Hello");
        set.add("World");
        set.add("foo");
        set.add("bar");
        set.add("42");
        WORDS = Collections.unmodifiableSet(set);
    }
}

Explicando qué es el método de sobrecarga y anulación.

El método de anulación y sobrecarga son dos formas de polimorfismo soportado por Java.

Método de sobrecarga

La sobrecarga de métodos (también conocida como Polimorfismo estático) es una forma en que puede tener dos (o más) métodos (funciones) con el mismo nombre en una sola clase. Sí, es tan simple como eso.

public class Shape{
    //It could be a circle or rectangle or square
    private String type;
    
    //To calculate area of rectangle
    public Double area(Long length, Long breadth){
        return (Double) length * breadth;
    }
    
     //To calculate area of a circle
     public Double area(Long radius){
        return (Double) 3.14 * r * r;
    }
}

De esta manera, el usuario puede llamar al mismo método para el área dependiendo del tipo de forma que tenga.

Pero la pregunta real ahora es, ¿cómo distinguirá el compilador Java qué cuerpo del método se ejecutará?

Bueno, Java ha dejado claro que aunque los nombres de los métodos ( area() en nuestro caso) pueden ser iguales, el método de los argumentos debe ser diferente.

Los métodos sobrecargados deben tener diferentes listas de argumentos (cantidad y tipos).

Dicho esto, no podemos agregar otro método para calcular el área de un cuadrado como este: public Double area(Long side) porque, en este caso, entrará en conflicto con el método del círculo del área y causará ambigüedad para el compilador Java.

Gracias a Dios, hay algunas relajaciones al escribir métodos sobrecargados como

Puede tener diferentes tipos de retorno.

Puede tener diferentes modificadores de acceso.

Puede lanzar diferentes excepciones.

¿Por qué se llama esto polimorfismo estático?

Bueno, eso se debe a que los métodos sobrecargados que se van a invocar se deciden en el momento de la compilación, según el número real de argumentos y los tipos de tiempo de compilación de los argumentos.

Una de las razones más comunes para usar la sobrecarga de métodos es la simplicidad del código que proporciona. Por ejemplo, recuerde String.valueOf() que toma casi cualquier tipo de argumento? Lo que está escrito detrás de la escena es probablemente algo como esto:

static String valueOf(boolean b) 
static String valueOf(char c) 
static String valueOf(char[] data) 
static String valueOf(char[] data, int offset, int count) 
static String valueOf(double d) 
static String valueOf(float f) 
static String valueOf(int i) 
static String valueOf(long l) 
static String valueOf(Object obj) 

Método Anulando

Bueno, el método de anulación (sí, supongo que es correcto, también se conoce como polimorfismo dinámico) es un tema algo más interesante y complejo.

En la sustitución de métodos, sobrescribimos el cuerpo del método proporcionado por la clase padre. ¿Lo tengo? ¿No? Veamos un ejemplo.

public abstract class Shape{
    
    public abstract Double area(){
        return 0.0;
    }
}

Así que tenemos una clase llamada Forma y tiene un método llamado área que probablemente devolverá el área de la forma.

Digamos que ahora tenemos dos clases llamadas Círculo y Rectángulo.

public class Circle extends Shape {
    private Double radius = 5.0;

    // See this annotation @Override, it is telling that this method is from parent
    // class Shape and is overridden here
    @Override
    public Double area(){
        return 3.14 * radius * radius;
    }
}

De forma similar clase de rectángulo:

 public class Rectangle extends Shape {
    private Double length = 5.0;
    private Double breadth= 10.0;


    // See this annotation @Override, it is telling that this method is from parent
    // class Shape and is overridden here
    @Override
    public Double area(){
        return length * breadth;
    }
}

Entonces, ahora las dos clases de sus hijos tienen el cuerpo del método actualizado proporcionado por la clase principal ( Shape ). Ahora la pregunta es ¿cómo ver el resultado? Bueno, psvm la vieja psvm .

public class AreaFinder{
    
    public static void main(String[] args){

        //This will create an object of circle class
        Shape circle = new Circle();
        //This will create an object of Rectangle class
        Shape rectangle = new Rectangle();
        
        // Drumbeats ......
        //This should print 78.5
        System.out.println("Shape of circle : "+circle.area());

        //This should print 50.0
        System.out.println("Shape of rectangle: "+rectangle.area());            
        
    }
}

¡Guauu! no es genial? Dos objetos del mismo tipo que llaman a los mismos métodos y devuelven valores diferentes. Mi amigo, ese es el poder del polimorfismo dinámico.

Aquí hay una tabla para comparar mejor las diferencias entre estos dos:

Método de sobrecarga Método Anulando
El método de sobrecarga se utiliza para aumentar la legibilidad del programa. La anulación del método se utiliza para proporcionar la implementación específica del método que ya está provisto por su superclase.
La sobrecarga de métodos se realiza dentro de la clase. La anulación del método se produce en dos clases que tienen una relación IS-A (herencia).
En caso de sobrecarga del método, el parámetro debe ser diferente. En caso de anulación del método, el parámetro debe ser el mismo.
La sobrecarga de métodos es el ejemplo del polimorfismo de tiempo de compilación. La anulación del método es el ejemplo del polimorfismo de tiempo de ejecución.
En java, la sobrecarga de métodos no se puede realizar cambiando solo el tipo de retorno del método. El tipo de retorno puede ser igual o diferente en la sobrecarga de métodos. Pero debes tener que cambiar el parámetro. El tipo de devolución debe ser igual o covariante en la invalidación del método.


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow