La clase Lugar

La aplicación Mis Lugares permite gestionar una colección de lugares. Para cada lugar vamos a poder almacenar mucha información: nombre, dirección, posición geográfica, etc. El primer paso a realizar va a ser crear una clase que nos permita trabajar en este tipo de información. Este tipo de clase se conoce muchas veces como POJO om clase de datos.

Ejercicio paso a paso: Creación de la clase Lugar

Android Studio está pensado exclusivamente para crear aplicaciones Android. Sin embargo, si sigues los siguientes pasos podrás crear una aplicación 100% Java o Kotlin.

1.    Crea un nuevo proyecto (File > New > New Project..) con los siguientes datos:

Phone and Tablet / No Activity
Name: Mis Lugares Java ó Mis Lugares Kotlin
Package name: com.example.mislugaresjava ó com.example.mislugareskotlin
Language: Java ó Kotlin
Minimum API level: API 19 Android 5.0 (Lollipop)

NOTA: Deja el resto de los parámetros con su valor por defecto.

2.   Pulsa en File > New > New Module. Selecciona Java or Kotkin Libraty.

Introduce en Library name: MisLugares, como pakage name: com.example.mislugares, es Class name: Lugar. y en Language: Java o Kotlin según prefieras. Pulsa el botón Finish. Se creará un nuevo módulo dentro de tu proyecto Android.

3.   Reemplaza el código  de la clase Lugar por el siguiente:

package com.example.mislugares

data class Lugar(val nombre: String,
                 var direccion: String = "",
                 var posicion: GeoPunto = GeoPunto.SIN_POSICION,
                 var foto: String = "",
                 var telefono: Int = 0,
                 var url: String= "",
                 var comentarios: String = "",
                 var fecha: Long = System.currentTimeMillis(),
                 var valoracion: Float = 3.5F
)
package org.example.mislugares;
public class Lugar {
       private String nombre;
       private String direccion;
       private GeoPunto posicion;
       private String foto;
       private int telefono;
       private String url;
       private String comentario;
       private long fecha;
       private float valoracion;

       public Lugar(String nombre, String direccion, double longitud,
             double latitud, int telefono, String url, String comentario,
             int valoracion) {
             fecha = System.currentTimeMillis();
             posicion = new GeoPunto(longitud, latitud);
             this.nombre = nombre;
             this.direccion = direccion;
             this.telefono = telefono;
             this.url = url;
             this.comentario = comentario;
             this.valoracion = valoracion;
       }
}

Para Java observa como se definen los atributos de la clase y como en el constructor se inicializa para un objeto concreto según los parámetros indicados. En estos parámetros no se indica el atributo fecha. Este representa el día y la hora en que visitamos ese lugar por última vez. Se codifica mediante un long (número entero de 64 bits), que supondremos en formato Epoch time o tiempo Unix [0]. Es decir, número de milisegundos transcurridos desde 1970.  El método System.currentTimeMillis() nos devuelve la fecha y hora actual en este formato. Por lo tanto, siempre que usemos este constructor, en fecha se almacenará el instante en que él objeto fue creado.
Para Kotlin en el constructor principal indicamos directamente las atributos de la clase y en algunos casos los valores por defecto. Los getters y setters son creados automáticamente. Además, al haber indicado data class se crean otras funciones como toString(). Por lo tanto podrás saltarte los siguientes dos puntos.

4.    Solo para Java crea los métodos getters y setters para acceder a todos los atributos de la clase. Solo tienes que pulsar con el botón derecho y seleccionar la opción  Generate… > Getter and Setter y  selecciona  todos los atributos mientras mantienes pulsada la tecla Ctrl.

5.    Solo para Java pulsa con el botón derecho sobre el código y selecciona la opción Generate... > toString()... Selecciona todos los atributos y pulsa en OK. Se añadirá un método similar a:

@Override
public String toString() {
       return "Lugar [nombre="+ nombre+ ", direccion="+ direccion
             + ", posicion="+ posicion+ ", foto="+ foto+ ", telefono="
             + telefono+ ", url="+ url+ ", comentario="+ comentario
             + ", fecha="+ fecha+ ", valoracion="+ valoracion+ "]";
}

NOTA: El significado de @Override se explica más adelante.

6.    Dentro del  explorador del proyecto mislugares > java > com.example.mislugares, pulsa con el botón derecho y selecciona New > Java Class o Kotlin File/Class. Introduce en el campo Name:   GeoPunto y pulsa Ok. Reemplaza el código por el siguiente (dejando la línea del package):

public class GeoPunto {

       private double longitud, latitud;
       
       static public GeoPunto SIN_POSICION = new GeoPunto(0.0,0.0);

       public GeoPunto(double longitud, double latitud) {
           this.longitud= longitud;
           this.latitud= latitud;
       }

       public String toString() {
           return new String("longitud:" + longitud + ", latitud:"+ latitud);
       }

       public double distancia(GeoPunto punto) {
           final double RADIO_TIERRA = 6371000; // en metros
           double dLat = Math.toRadians(latitud - punto.latitud);
           double dLon = Math.toRadians(longitud - punto.longitud);
           double lat1 = Math.toRadians(punto.latitud);
           double lat2 = Math.toRadians(latitud);
           double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                      Math.sin(dLon/2) * Math.sin(dLon/2) *
                      Math.cos(lat1) * Math.cos(lat2);
           double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
           return c * RADIO_TIERRA;
       }
}
data class GeoPunto(var longitud: Double, var latitud: Double) {
    companion object {
      val SIN_POSICION = GeoPunto(0.0,0.0)
   }

   fun distancia(punto: GeoPunto): Double {
      val RADIO_TIERRA = 6371000.0 // en metros
      val dLat = Math.toRadians(latitud - punto.latitud)
      val dLon = Math.toRadians(longitud - punto.longitud)
      val lat1 = Math.toRadians(punto.latitud)
      val lat2 = Math.toRadians(latitud)
      val a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + 
              Math.sin(dLon / 2) * Math.sin(dLon / 2) *
              Math.cos(lat1) * Math.cos(lat2)
      val c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
      return c * RADIO_TIERRA
   }
}

El objeto SIN_POSICION, será utilizado cuando se quiera indicar que un lugar no tiene posición asignada. Observa que es un objeto de tipo estático. En Java se indica con static y en Kotlin con companion object. Esto significa que solo va a haber una instancia de este objeto creada desde el principio. Para acceder a ella usaremos GeoPunto.SIN_POSICION.

7.    Solo para Java crea  en esta clase los métodos getters y setters para acceder a los dos atributos. Igual que antes, pulsa con el botón derecho y seleccionar la opción Generate… > Getter and Setter.  Realiza la misma operación para equals() and hasCode().

8.   Para Java y Kotlin crea una nueva clase Java con nombre: Principal . Android Studio no permite que la clase principal esté en Kotlin. Reemplaza el código por el mostrado (dejando la línea del package):

class Principal {
       public static void main(String[] main) {
         Lugar lugar = new Lugar("Escuela Politécnica Superior de Gandía",
              "C/ Paranimf, 1 46730 Gandia (SPAIN)",
              new GeoPunto(-0.166093, 38.995656) ,
              "",
              962849300, 
              "http://www.epsg.upv.es",
              "Uno de los mejores lugares para formarse.",
              System.currentTimeMillis(), 
              3);
         System.out.println("Lugar " + lugar.toString());
       }
}
class Principal {
       public static void main(String[] main) {
         Lugar lugar = new Lugar("Escuela Politécnica Superior de Gandía",
              "C/ Paranimf, 1 46730 Gandia (SPAIN)", -0.166093, 38.995656,
              962849300, "http://www.epsg.upv.es",
              "Uno de los mejores lugares para formarse.", 3);
         System.out.println("Lugar " + lugar.toString());
       }
}

La clase Principal es algo atípica: no tiene atributos ni constructor, únicamente el método main. Cuando en un proyecto existe una clase que tiene un método con este perfil, es el que se llama para comenzar la ejecución. Como parámetros, este método recibe un array de Strings. Esta información tiene interés cuando el programa se ejecuta desde la línea de comandos con parámetros.

Si trabajas con Kotlin has de usar un constructor diferente, dado que este tiene más parámetros.

9.   Pulsa en el botón desplegable a la derecha del botón Run . Selecciona Edit Configurations...


 

10.    En la nueva ventana, haz clic en  el  signo + de la esquina superior izquierda y selecciona Application. Aparecerá una nueva configuración de aplicación. Selecciona en Name: mislugares, en Use classpath of module: Mis_lugares_Java.MisLugares y en Main class: com.example.mislugares.

11.   Pulsa el botón Ejecución y verifica que el resultado que aparece en la ventana de Run es similar a:

“C\Program ...

Lugar {nombre=Escuela Politécnica Superior de Gandía,
direccion=C/ Paranimf, 1 46730 Gandia (SPAIN),
posicion=longitud:-0.166093, latitud:38.995656, foto=null,
telefono=962849300, url=http://www.epsg.upv.es,
comentario=Uno de los mejores lugares para formarse.,
fecha=1392332854758, valoracion=3.0}

Process finished with exit code 0