CodeGym /Blog Java /Random-ES /Clases de Java: escribir sus propias clases, constructore...
John Squirrels
Nivel 41
San Francisco

Clases de Java: escribir sus propias clases, constructores

Publicado en el grupo Random-ES
¡Hola! Hoy hablaremos de las clases en Java. Se podría decir que las clases forman la piedra angular de la programación Java. Cuando te conviertas en programador, casi todo tu trabajo será escribir tus propias clases que tienen varias funciones. Veamos qué significa eso y cómo funciona. :) Como sabes, Java es un lenguaje de programación orientado a objetos. Todos los programas están formados por objetos que de una forma u otra están relacionados entre sí. Una clase es, esencialmente, una plantilla para un objeto. Determina cómo se verá el objeto y qué funciones tendrá. Todo objeto es un objeto de alguna clase. Considere este ejemplo muy simple:

public class Cat {

    String name;
    int age;

}
Digamos que estamos escribiendo un programa que involucra gatos por alguna razón (por ejemplo, tenemos una clínica veterinaria que ofrece acceso a una cuenta en línea). Creamos una clase Cat y declaramos dos variables en ella: String name e int age . Estas variables miembro se denominan campos. Esencialmente, esta es una plantilla para todos los gatos que crearemos en el futuro. Cada objeto Cat tendrá dos variables: un nombre y una edad.

public class Cat {

    String name;
    int age;

    public static void main(String[] args) {
        Cat smudge = new Cat();
        smudge.age = 3;
        smudge.name = "Smudge";

        System.out.println("We created a cat named " + smudge.name + ". His age is " + smudge.age);
    }

}
¡Así es como funciona! Creamos un gato, le damos un nombre y una edad, y lo mostramos todo en la consola. Pedazo de pastel. :) La mayoría de las veces, las clases describen cosas y fenómenos del mundo real. Un gato, una mesa, una persona, un rayo, una página de un libro, una rueda: creará todas estas cosas en sus programas usando clases individuales. Por ahora, concentrémonos en las variables que declaramos en la clase Cat . Se denominan campos o variables de instancia. Su nombre realmente lo dice todo. Cada instancia (u objeto) de la clase Cat tendrá estas variables. Cada gato que creemos tendrá su propia variable de nombre y su propia edadvariable. Esto tiene sentido, es básicamente lo que sucede con los gatos reales. :) Además de las variables de instancia, también hay variables de clase (variables estáticas). Terminemos nuestro ejemplo:

public class Cat {

    String name;
    int age;

    static int count = 0;

    public static void main(String[] args) {
        Cat smudge = new Cat();
        smudge.age = 3;
        smudge.name = "Smudge";
        count++;

        Cat fluffy = new Cat();
        fluffy.age = 5;
        fluffy.name = "Fluffy";
        count++;

        System.out.println("We created a cat named " + smudge.name + ". His age is " + smudge.age);
        System.out.println("We created a cat named " + fluffy.name + ". His age is " + fluffy.age);

        System.out.println("Total number of cats = " + count);
    }
}
Salida de la consola: creamos un gato llamado Smudge. Su edad es 3 Creamos un gato llamado Fluffy. Su edad es 5 Número total de gatos = 2 Ahora nuestra clase tiene una nueva variable llamada contar. Se encarga de contar los gatos creados. Cada vez que creamos un gato en el principalmétodo, aumentamos esta variable en 1. Esta variable se declara usando la palabra clave static. Eso significa que pertenece a la clase, no a un objeto específico de la clase. Lo cual, por supuesto, tiene sentido: el nombre de cada gato pertenece a ese gato específico, pero necesitamos un contador de gatos que se aplique a todos ellos. Esto es precisamente lo que logra la palabra clave static: convierte la variable de conteo en una única variable para todos los gatos. Nota: cuando mostramos la variable, no estamos usando smudge.count o fluffy.count. No pertenece ni a Smudge ni a Fluffy; pertenece a toda la clase Cat . Es por eso que es simplemente contar. También podría escribir Cat.count. Eso también sería correcto. Al mostrar la variable de nombre, no haríamos lo siguiente:

public class Cat {

    String name;
    int age;

    static int count = 0;

    public static void main(String[] args) {
        Cat smudge = new Cat();
        smudge.age = 3;
        smudge.name = "Smudge";
        count++;

        System.out.println("We created a cat named " + name + ". His age is " + smudge.age);

        System.out.println("Total number of cats = " + count);
    }
}
¡Esto es un error! Cada gato tiene su propio nombre. El compilador se confunde aquí. "¿Enviar un nombre a la consola? ¿El nombre de quién?" :/"

Métodos

Además de las variables, cada clase tiene métodos. Hablaremos de ellos con más detalle en una lección separada, pero los principios generales son bastante simples. Los métodos definen la funcionalidad de su clase, es decir, qué pueden hacer los objetos de su clase. Ya estás familiarizado con uno de estos métodos: el método main() . Pero, como recordarás, el método principal es estático, lo que significa que pertenece a toda la clase (la lógica es la misma que con las variables). Sin embargo, los métodos estándar no estáticos solo se pueden llamar en objetos específicos que hemos creado. Por ejemplo, si queremos escribir una clase de gato, necesitamos saber qué funciones debe tener un gato en nuestro programa. Partiendo de esa premisa, escribamos un par de métodos para nuestro gato:

public class Cat {

    String name;
    int age;

    public void sayMeow() {
        System.out.println("Meow!");
    }

    public void jump() {
        System.out.println("Pounce!");
    }

    public static void main(String[] args) {
        Cat smudge = new Cat();
        smudge.age = 3;
        smudge.name = "Smudge";

        smudge.sayMeow();
        smudge.jump();

    }
}
¡Échale un vistazo! ¡Ahora nuestra clase está mucho más cerca de parecerse a un gato! Ahora no solo tenemos un gato con un nombre ("Smudge") y una edad (3). ¡También puede decir miau y saltar! ¿Qué tipo de gato sería sin esa "funcionalidad"? :) Estamos tomando un objeto específico (mancha) y llamando a sus métodos sayMeow() y jump() . Miremos la consola: ¡Miau! ¡Saltar! ¡Un gato de verdad! :)

Creando tus propias clases. Abstracción

En el futuro, tendrás que escribir tus propias clases. ¿Qué necesitas tener en cuenta cuando los escribes? Si estamos hablando de variables, entonces necesitará hacer uso de algo llamado abstracción. La abstracción es uno de los cuatro principios básicos de la programación orientada a objetos. Significa extraer las características más importantes y significativas de un elemento y, por el contrario, descartar las que son menores o insignificantes. Por ejemplo, creemos un archivador para los empleados de la empresa. Para crear objetos de empleado, hemos escrito un Empleadoclase. ¿Qué características son descriptores importantes de un empleado para el archivador de nuestra empresa? Nombre, fecha de nacimiento, SSN e identificación de empleado. Pero es poco probable que necesitemos la altura, el color de los ojos o el color del cabello del empleado para el registro de empleados de la empresa. Las empresas no necesitan esta información. Entonces, en la clase Employee , declaramos las siguientes variables: String name , int age , int socialSecurityNumber e int employeeId. Y dejamos fuera información innecesaria (como el color de ojos). En otras palabras, creamos una abstracción. Sin embargo, si estamos haciendo un archivador para agencias de modelos, la situación cambia drásticamente. La altura, el color de los ojos y el color del cabello de una modelo son características importantes, pero su SSN es absolutamente irrelevante para nosotros. Entonces, en la clase Model , necesitamos crear las siguientes variables: String height , String hair , String eyes . Así es como funciona la abstracción: ¡es fácil! :)

Constructores

Volvamos a nuestro ejemplo del gato.

public class Cat {

    String name;
    int age;

    public static void main(String[] args) {
        Cat smudge = new Cat();

        System.out.println("Here the program does something for 2 hours...");

        smudge.age = 3;
        smudge.name = "Smudge";

    }
}
Mire este código e intente descubrir qué está mal con nuestro programa. ¡Nuestro programa tuvo un gato sin nombre ni edad durante 2 horas! Por supuesto, esto es inherentemente incorrecto. La base de datos de la clínica veterinaria no debe incluir gatos sin información. Actualmente, nuestro gato está a merced del programador. Confiamos en que no olvidará especificar un nombre y una edad, y que todo saldrá bien. Si se olvida, la base de datos tendrá un problema: gatos sin nombre. ¿Cómo podemos solucionar este problema? Debemos evitar de alguna manera que se creen gatos sin nombre y sin edad. Aquí es donde los constructores vienen al rescate. Pongamos un ejemplo:

public class Cat {

    String name;
    int age;

    // Constructor for the Cat class
    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat smudge = new Cat("Smudge", 5);
    }
}
Esencialmente, un constructor es una plantilla para objetos de una clase. En este caso, indicamos que se deben especificar dos argumentos, un String y un int , para cada objeto cat . Si intentamos crear un gato sin nombre ahora, no funcionará.

public class Cat {

    String name;
    int age;

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat smudge = new Cat(); // Error!
    }
}
Ahora que la clase tiene un constructor, el compilador de Java sabe cómo deben verse los objetos y no permite que se creen objetos sin especificar los argumentos. Ahora, investiguemos la palabra clave this, que ves dentro del constructor. Es simple también. La palabra clave this es para indicar un objeto en particular. El código en el constructor.

public Cat(String name, int age) {
    this.name = name;
    this.age = age;
}
se puede interpretar casi textualmente: "El nombre de este gato (el que estamos creando) = el argumento pasado para el parámetro del nombre del constructor. La edad de este gato (el que estamos creando) = el argumento pasado para el parámetro del constructor parámetro de edad". Después de que se ejecute el constructor, puede verificar que todos los valores necesarios se hayan asignado a nuestro gato:

public class Cat {

    String name;
    int age;

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat smudge = new Cat("Smudge", 5);
        System.out.println(smudge.name);
        System.out.println(smudge.age);
    }
}
Salida de la consola: Smudge 5 Cuando se llamó al constructor:

Cat smudge = new Cat("Smudge", 5);
Esto es lo que realmente sucedió internamente:

this.name = "Smudge";
this.age = 5;
Y los valores de los argumentos pasados ​​​​al constructor se asignaron al objeto de mancha (a eso se refiere en este caso). De hecho, incluso si no declara ningún constructor en una clase, ¡todavía llamará a un constructor! Pero, ¿cómo es posible? О_О Porque todas las clases de Java tienen un llamado constructor predeterminado. No toma ningún argumento, pero se invoca cada vez que crea un objeto de cualquier clase.

public class Cat {

    public static void main(String[] args) {

        Cat smudge = new Cat(); // The default constructor is invoked here
    }
}
A primera vista, esto puede no ser obvio. Creamos un objeto, ¿y qué? ¿Dónde está el constructor haciendo algo aquí? Para verlo, escribamos explícitamente un constructor vacío para la clase Cat . En su interior, enviaremos alguna frase a la consola. Si se muestra la frase, entonces se invocó al constructor.

public class Cat {

    public Cat() {
        System.out.println("A cat has been created!");
    }

    public static void main(String[] args) {

        Cat smudge = new Cat(); // The default constructor is invoked here
    }
}
Salida de la consola: ¡Se ha creado un gato! Ahí está la confirmación. El constructor predeterminado siempre está presente de forma invisible en sus clases. Pero necesitas saber una cosa más al respecto. El constructor predeterminado se elimina de una clase una vez que crea un constructor con argumentos. De hecho, ya hemos visto pruebas de esto arriba. Estaba en este código:

public class Cat {

    String name;
    int age;

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat smudge = new Cat(); // Error!
    }
}
No podíamos crear un gato sin nombre y edad, porque declaramos un constructor de gato con parámetros de cadena e int. Esto provocó que el constructor predeterminado desapareciera inmediatamente de la clase. Así que asegúrese de recordar que si necesita varios constructores en su clase, incluido un constructor sin argumentos, deberá declararlo por separado. Nuestra clínica quiere hacer buenas obras y ayudar a gatitos sin hogar cuyos nombres y edades se desconocen. Entonces nuestro código debería verse así:

public class Cat {

    String name;
    int age;

    // For cats with owners
    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // For street cats
    public Cat() {
    }

    public static void main(String[] args) {
        
        Cat smudge = new Cat("Smudge", 5);
        Cat streetCat = new Cat();
    }
}
Ahora que hemos especificado un constructor predeterminado explícito, podemos crear ambos tipos de gatos. En el constructor, puede asignar valores directamente. No tienes que tomarlos siempre de argumentos. Por ejemplo, podríamos etiquetar todos los gatos callejeros en la base de datos usando "Número de gato callejero <recuento>" como plantilla. :

public class Cat {

    String name;
    int age;

    static int count = 0;

    public Cat() {
        count++;
        this.name = "Street cat No. " + count;
    }

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat streetCat1 = new Cat();
        Cat streetCat2 = new Cat();
        System.out.println(streetCat1.name);
        System.out.println(streetCat2.name);
    }
}
Tenemos una variable de recuento , que cuenta nuestros gatos callejeros. Cada vez que se ejecuta el constructor predeterminado, aumentamos la cuenta en 1 y adjuntamos este número al nombre del gato. El orden de los argumentos es muy importante para los constructores. Intercambiemos los argumentos de nombre y edad pasados ​​a nuestro constructor.

public class Cat {

    String name;
    int age;

    public Cat(int age, String name) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat smudge = new Cat("Smudge", 10); // Error!
    }
}
¡Tenemos un error! El constructor estipula claramente que cuando se crea un objeto Cat , se le debe pasar un número y una cadena, en este orden. Entonces, nuestro código no funciona. Asegúrese de recordar y respetar esta regla cuando declare sus propias clases:

public Cat(String name, int age) {
    this.name = name;
    this.age = age;
}

public Cat(int age, String name) {
    this.age = age;
    this.name = name;
}
¡Estos son dos constructores totalmente diferentes! Ahora, complete un par de tareas para solidificar su comprensión del material. :)
  1. Museo de Antigüedades.

    Su tarea es diseñar una clase de artefacto .
    Hay tres tipos de artefactos guardados en el museo.
    No sabemos nada del primer tipo excepto el número de serie asignado por el museo (por ejemplo: 212121).
    Para el segundo tipo, conocemos el número de serie y la cultura que lo creó (por ejemplo: 212121, "Aztecas").
    Para el tercer tipo, sabemos el número de serie, la cultura que lo creó y el siglo en que fue creado (por ejemplo: 212121, "Aztecas", 12).

    Cree una clase de Artefacto que describa las antigüedades guardadas en el museo y escriba el conjunto requerido de constructores para la clase. Luego, en el método main() , cree un artefacto de cada tipo.

    
    public class Artifact {
        
        // Write your code here
    
        public static void main(String[] args) {
            // Write your code here
        }
    }
    
  2. sitio web de citas

    Vamos a crear una base de datos de usuarios para un sitio web de citas.
    Pero aquí está el problema: olvidó el orden requerido de los argumentos y no hay documentación técnica disponible.
    Diseñe una clase de usuario , que tendrá los siguientes campos: nombre ( String ), edad ( short ) y altura ( int ).
    Cree el número apropiado de constructores, de modo que el nombre, la edad y la altura se puedan especificar en cualquier orden.

    
    public class User {
    
        String name;
        short age;
        int height;
    
        // Write your code here
    
        public static void main(String[] args) {
            
        }
    }
    
Para reforzar lo que aprendió, le sugerimos que vea una lección en video de nuestro Curso de Java
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION