Clases y objetos. Atributos y métodos.

 

Programar implica tres cosas:

1.- Repetir innumerables veces la teoría para lograr tener claro las ideas y conceptos con los que se mueve el lenguaje Java. Al principio los conceptos los confundirás. Hasta que queden nítidos y claros tendrás que repetir mil veces.

2.- Hacer innumerables ejercicios en el ordenador para asentar esos conceptos.

3.- Volver a repetir una y otra vez los conceptos con la teoría y la práctica.

Según Platón y Aristóteles existen los universales, para Platón los universales existen en un mundo distinto o de las Ideas, para Aristóteles existen en las cosas mismas, en los objetos concretos: es lo que tienen de común esos objetos, que hacen que pertenezcan a una clase o tipo de objeto. 

Pues bien, para la POO las Clases son los Universales o las Ideas, y los objetos son los entes concretos, las sustancias: los seres que son, individualizados y existentes en sí mismos, aunque concretando un universal. No existe un ente que no forme parte de un universal. Como no existe un objeEn la POO "diseccionamos" el objeto en lo que en metafísica sería su ser y su operar, y esto lo definimos al definir su Clase. 

En OOP un objeto es un conjunto de:

  • Datos (Su ser)
  • Métodos (Su operar)

Que vienen determinados en la definición de la Clase (p.ej. Mesa) que hagamos.
El método constructor es un método especial, que, invocado por el operador new, inicializa las propiedades -variables atributo- de un objeto.Datos que pueden ser propiedades de las mesas, por ejemplo, su color, número de patas, su forma.El constructor inicializa las propiedades:
public void Mesa(String color, int numPatas, String forma){color = nuevoColor;numPatas = nuevoNumPatas;forma = nuevaForma;} Mesa mAalto = new Mesa("transparente", 4,"cuadrada");
Es una mesa esquemática, de un nivel de definición muy bajo. Pero puede servir de modo descriptivo:La mesa mAalto es transparente, de cuatro patas y cuadrada.
Supongamos dos objetos semejantes, por ejemplo, dos mesas. Así, si tenemos una clase Mesa y dos o más “objetos mesa”, cada uno con datos diferentes, tenemos dos mesas diferentes, podríamos también tener mesas iguales, y podríamos modificar sus propiedades.

Debido a que los datos o valores de un objeto definen en parte este objeto (lo diferencian de los demás), a veces llamamos a estos datos “Propiedades”. También, se les llama, en la definición de la Clase, variables atributos.

Métodos, alguna operación propia de la mesa? El operar de la mesa, por ella misma, es nulo, pero un pintor si puede cambiarle el color. De momento supongamos que es la misma mesa, por sí misma, la que cambia el color. Suponemos que cambiar el color es un verbo reflexivo, luego veremos que propiamente es transitivo: el pintor cambia el color, pinta la mesa. Ya hemos dicho que, ahora, la mesa se pinta a sí misma.

La definición de la clase Mesa.java empezaría así:

class Mesa {

String color;int numPatas;String forma;
public void Mesa(String color, int numPatas, String forma){color = nuevoColor;numPatas = nuevoNumPatas;forma = nuevaForma;
void cambiarColor(String "verde"){color = "verde";}}

Con esto estamos definiendo las variables atributo de la mesa tal como ahora queremos:

Que tenga un color: variable de tipo String.
Que tenga un número de patas, variable de tipo int.
Que tenga una forma: variable tipo String.

Con ello definimos lo que se llama la estructura de la Clase, o su ser.

El método main:
El método main es el método principal, es el método que inicia la ejecución del programa.
Es un método public, static o de clase, void -no devuelve ningún valor- y siempre se escribe con parámetros formales: 
public static void main(String[] arg){}

Este método inicia la ejecución del programa fuente da Java, con el número de Clases que tenga ralacionadas entre sí, lo compila y nos dice si hay errores de compilación o de ejecución, no lógicos.

Ej:

class Inicio {


public static void main(String[] arg){
Mesa mAalto = new Mesa("roja", 4, "redonda");// nos fabrica la mesa mAalto con esas propiedades.
mAalto.cambiarColor("transparente");// nos cambia el color rojo por transparente.
}

}

pero nosotros no lo vemos. Sólo si hacemos un System.out.println(mAalto.get(color)); nos dice de qué color es.... Así quedaría:

class Inicio {

 

public static void main(String[] arg){
Mesa mAalto = new Mesa("roja", 4, "redonda");
// nos fabrica la mesa mAalto con esas propiedades.
System.out.println(mAalto.get(color));

mAalto.cambiarColor("transparente");// nos cambia el color rojo por transparente.

}
}

Al definir los o el método cambiarColor(), que sería su operar. (Reflexivo, ahora). De este modo:

 void cambiarColor(String "verde"){
color = "verde";
}

Métodos setter y getter:

Hay unos métodos predeterminados que realizan las acciones de cambiar las propiedades -una a una o individualmente- de los objetos, setters; o bien no mostrarían esas propiedades con sus valores actuales: getters.

Para esta clase Mesa, serían:

public void setColor(String color)
{this.color = color;}

public void setNumPatas(int numPatas)
{this.numPatas= numPatas;}

public String setForma(String forma)
{this.forma = forma;}

This es el "objeto actual" que, como todos los objetos, pueden invocar con punto (.) no sólo los métodos, sino también los atributos, siempre que sean visibles.

Los getters:

public String getColor()
{return color;}

public int getNumPatas()
{return numPatas;}

public String getForma()
{return forma;}

Como vemos, los setter son métodos -tienen paréntesis detrás del nombre o identificador- que tienen parámetros, que son los valores que les daremos para que los adquieran los objetos. En el cuerpo del método le indicamos que los cambien sin más.

Los getters nos permiten no sólo saber, sino obtener para poder utilizar los valores que tengan esas variables. Ahí está la diferencia entre un método void y uno return.

 

Toda Clase que tenga variables atributo necesariamente al menos tendrá un Constructor, el constructor por defecto, y tantos como podamos combinar los atributos, siendo parámetros formales del Constructor.

El constructor por defecto será del tipo:

                public Mesa(){

}

E iniciará las propiedades de la mesa a los valores null, para "color", 0 para numPatas y null para "forma";

podríamos tener tantos constructores como estos:

public Mesa(String color){}; public Mesa(int numPatas){}; public Mesa(String forma){};

public Mesa(String color, int numPatas){};public Mesa(String color, String forma){};public Mesa(int numPatas, String forma){}; public Mesa(String color, int numPatas, String forma){};

public Mesa(Mesa m1){};

En el cuerpo de los métodos constructores los hemos dejado vacíos los definiremos como nos interese.

Podria quedar así: 

 



Como se vé, el constructor que está en la fila 11 no lo admite, pues tiene un parámetro y del tipo String, es decir, no se pueden repetir el o los mismos tipos de parámetros formales en el mismo orden.
El constructor último, cuyo parámetro es del mismo tipo que el objeto que construye, es decir, una mesa, puede adquirir los mismos valores de las propiedades de la mesa, con lo cual construimos clones, o podemos construir, a partir del parámetro formal mesa, otras mesas que las modifiquen, según el código del cuerpo del método constructor.

En el cuerpo de los métodos hay que indicar y definir lo que hacen y como la hacen. Si los dejamos vacíos no hacen nada, aunque en el perfil les demos parámetros materiales.


public class Mesa {
String color;
int numPatas;
String forma;
public Mesa(){}
public Mesa(String color){this.color=color;};
public Mesa(int numPatas){this.numPatas=numPatas;};
//public Mesa(String forma){this.forma=forma;};
public Mesa(String color, int numPatas){};
public Mesa(String color, String forma){};
public Mesa(int numPatas, String forma){}; 
public Mesa(String color, int numPatas, String forma){
this.color = color;this.numPatas = numPatas; this.forma = forma;}
public Mesa(Mesa m1){
this.color = m1.color; this.numPatas = m1.numPatas; this.forma =m1.forma;}
   
    public static void main(String[] args) {


        Mesa m1 = new Mesa("verde", 4, "redonda");        
        Mesa m2 = new Mesa(m1);//que no es lo mismo que:
        Mesa m3 = m2;//m3 y m2 es la misma mesa con dos nombres o referencias distintas;
        //si cambiamos las propiedades de m3 con los set, cambian -es el mismo objeto- los de m2.
        
       System.out.println("m1 "+ m1.toString());
        System.out.println("m2 "+ m2.toString());
         System.out.println("m3 "+ m3.toString());
         
         m3.setForma("cuadrada");
         System.out.println("m1 "+ m1.toString());
         System.out.println("m2 "+ m2.toString());
         System.out.println("m3 "+ m3.toString());
         
    }
    public String toString(){
        String st = this.color+"; "+this.numPatas+"; "+this.forma;  
        return st;
    }
    
    public void setColor(String color){this.color = color;}
    public void setNumPatas(int numPatas){this.numPatas = numPatas;}
    public void setForma(String forma){this.forma = forma;}
    public String getColor(){return color;} 
    public int getNumPatas(){return numPatas;} 
    public String getForma(){return forma;} 
          
}

El resultado de ejecutar este programita es:

run:

m1 verde; 4; redonda
m2 verde; 4; redonda
m3 verde; 4; redonda

Hemos cambiado la forma de m3 con un set y en la m2, como es el mismo objeto, cambia también:
m1 verde; 4; redonda
m2 verde; 4; cuadrada
m3 verde; 4; cuadrada

 Acabamos de ver un tipo muy especial de métodos, que son los constructores.

Los métodos, en general, podemos decir que son operadores: hacen las operaciones que les decimos y como se lo decimos.

Se clasifican en dos grandes mundos: los métodos estáticos y los dinámicos. También podemos decir que los métodos estáticos son los métodos de Clase, y los dinámicos los métodos de objetos.

Otra gran clasificación son los métodos que "devuelven" un valor, -hagan o no algo-, y los métodos que no devuelven un valor, hagan o no algo: por ejemplo los métodos setter hacen algo -cambian las características o propiedades de un objeto- pero no devuelven nada. Los métodos getter devuelven -return- cual es el valor de una de las propiedades de un objeto, pero no le hacen nada al objeto. Pero también hay métodos que cambian las propiedades de un objeto y devuelven un valor. Podemos definirlos como nos interesen, hay millones de posibilidades, pero hemos de actuar con muchísimo rigor a la hora de definirlos para que se comporten como deseamos.

Y una tercera manera de definirlos es según cómo adquieren los datos o valores con los que trabajan:
por ejemplo: mediante una variable local, definida e inicializada en el mismo método; o mediante una variable atributo, definida en la Clase, o mediante una variable definida en otra Clase a la que tenemos acceso por ser pública, o mediante parámetros formales, definidos en los paréntesis del método, como hemos visto en casi todos los constructores.

 

Por ejemplo, si definimos un método dinámico tal como este:

 

public void darDimensiones(){   

        int diametro = 0; int lado=0;int a=0; int b=0; int altura = 95;

        if (forma=="circular") diametro=120;

        if (forma=="cuadrada") lado = 110;

        if (forma=="rectangular") a = 100; b = 140;}

estaríamos utilizando variables locales como diametro, lado, a, b, altura.

y variables de objeto, como forma, que, según los valores que tuviera la forma del objeto creado con el Constructor, asignaría unos valores u otros; pero ojo estos valores no los tomaría el objeto en cuestión, pues son variables locales y no parámetros o atributos del objeto, pues no están definidos en la cabecera de la clase. Los objetos -mesas- no tienen diámetro, ni altura, ... en nuestra definición actual. 

Para que los tuviera, tendríamos que añadirlos en la cabecera de la Clase Mesa. Pero como son atributos locales, y no todas las mesas tienen que tener un int diametro, un  int a, int b, ...Pero tenemos el inconveniente que la forma puede tener varios valores String que, según los mismos, podemos asignárselos en el constructor:

    

public Mesa(){   

        int diametro = 0; int lado=0;int a=0; int b=0; int altura = 95;

        if (forma=="circular") diametro=120;

        if (forma=="cuadrada") lado = 110;

        if (forma=="rectangular") a = 100; b = 140;}

 

pero no tendríamos acceso al valor que tengan esas variables locales.

 

Los atributos tipo String no pueden tomar valores o dimensiones numéricos. Las variables locales desaparecen terminado el método.

 

Para que tengamos una mesa con esos atributos y valores, tendríamos que empezar definiendo clases mas detalladas, por ejemplo:

 

public class Punto2D{

int x;

int y;

 

public Punto2D(int x, int y){//Constructor con dos parámetros formales. Los valores se les dan por teclado o por código fuente.

this x = x;

this y = y;

}

    public static void main(String[] arg){//Método principal o de ejecución del programa

    Punto2D p1 = new Punto2D(0,0); //El punto p1 está en la posición (0,0).

    }

}

Comentarios