Definición de clases

Se desea definir una clase Punto que implementa las siguientes operaciones:

Punto p= new Punto(3, 4);
System.out.println(p);     // (3,4)

p.moverEn(1, 2);
System.out.println(p);     // (11,12)
Observación: cuando System.out.println recibe como argumento el objeto p, entonces invoca p.toString() y despliega el string retornado por este método.


Ejercicio:

R.-


Para definir una clase se usa:

public class Nombre {
  // Definiciones
  Constructores
  Variables de instancia de objetos
  Métodos
  Variables estáticas (compartidas)
  Métodos estáticos
}


Definición de la clase Punto

La clase debe estar definida en un archivo Punto.java con contenido:

public class Punto {
  int x, y; // Variables de instancia

  public Punto(int x, int y) { // El constructor
    this.x= x; this.y= y;
  }
  public void moverEn(int dx, int dy) { // Un método
    this.x+= dx; this.y+= dy;
  }
  public String toString() { // Otro método
    return "("+this.x+","+this.y+")";
  }
}



La invocación de un método

El paso de parámetros es por valor.


Definición de métodos



Ejercicio: definir el método moverA.

R.-


Ejemplo: Se desea agregar un método a la clase Punto que calcule la distancia entre este punto y un segundo punto recibido como argumento:

Punto p= new Punto(100, 100);
Punto q= new Punto(103, 104);

System.out.println( p.distanciaA(q) ); // 5
System.out.println( q.distanciaA(p) ); // 5
System.out.println( p.distanciaA(p) ); // ?


Solución:

public class Punto {
  ...
  public double distanciaA(Punto punto) {
    int dx= punto.x - this.x;
    int dy= punto.y - this.y;
    return Math.sqrt(dx*dx+dy*dy);
  }
}
Un objeto puede referenciar variables de otra instancia del mismo objeto.


Un método también puede invocar otros métodos y retornar objetos.

Ejemplo: un método que recibe 2 puntos y entrega aquel que esté más lejos de este punto.

public class Punto {
  ...
  public Punto masLejano(Punto p, Punto q) {
    if (this.distanciaA(p) >= this.distanciaA(q))
      return p;
    else
      return q;
  }
}


Ejemplo de uso:

Punto p= new Punto(100, 100);
Punto r= p.masLejano(new Punto(101,101), new Punto(1,1));
System.out.println(r); // (1,1)
Obs: el objeto de la invocación del método masLejano es referenciado por la variable p.

En la definición del método masLejano este objeto es referenciado por otro identificador. ¿Cuál?


Ejercicio: agregue el método suma a la clase Punto. El método debe sumar este punto con un segundo punto recibido como argumento y entregar el resultado en un nuevo punto.

Punto p= new Punto(10, 100);
Punto q= new Punto(20, 100);

Punto r= p.suma(q);

System.out.println(r); // (30,200)

// Cuidado! los puntos p y q no deben ser alterados
System.out.println(p); // (10,100)
System.out.println(q); // (20,100)


Resuelva este problema de la siguiente forma:

public class Punto {
  ...
  // El método recibe un punto como argumento y
  // entrega como resultado un nuevo punto:
  public Punto suma(Punto p) {
    Obtenga las coordenadas de este punto con
         this.x y this.y
    Obtenga las coordenadas de p con
         p.x y p.y
    Sume coordenada a coordenada estos valores
    y construya un nuevo punto con el resultado
    (usando new)
    Retorne el resultado al invocador mediante
    return el nuevo punto;
  }
}


R.-


Las variables de instancia se pueden accesar sin pasar por this (si no hay ambiguedad con variables locales). La clase Punto se puede reescribir:

public class Punto {
  int x, y; // Variables de instancia
  public Punto(int x, int y) { // El constructor
    this.x= x; this.y= y; // no se puede suprimir this
  }
  public void moverEn(int dx, int dy) { // Un método
    // this.x += dx; this.y += dy;
    x += dx; y += dy;
  }
  public String toString() { // Otro método
    // return "("+ this.x +","+ this.y +")";
    return "("+ x +","+ y +")";
  }
  ...
}


De la misma forma, se pueden invocar otros métodos del mismo objeto sin pasar por this. El método masLejano se puede reescribir:

public class Punto {
  ...
  public Punto masLejano(Punto p, Punto q) {
    // if (this.distanciaA(p) >= this.distanciaA(q))
    if (distanciaA(p) >= distanciaA(q))
      return p;
    else
      return q;
  }
}


Sobrecarga de métodos


Al invocar un método, el compilador busca en la clase el método que corresponda a los argumentos de la invocación.

  Punto p= new Punto(10,10);
  Punto q= new Punto(100,100);

  p.moverA(q);     // busca moverA(Punto)
  p.moverA(0,0);   // busca moverA(int,int)
  p.moverA("la esquina"); // Error en compilación


Propuesto: Ordenamiento de Arreglo

Si Ud. dispone de tiempo, le resultará muy instructivo realizar el ejercicio Ordenamiento de Arreglos que aparece en los apéndices.