domingo, 30 de abril de 2017

Un resumen de Scala for the Impatient, parte 17




Objetos que extienden de clases o trait

Un objeto puede extender de una clase y/o una o más traits. El resultado es un objeto que tiene las características de la clase y/o traits y puede agregar características propias.

Esto puede ser muy útil, por ejemplo para implementar el patrón NullObject. En el cual modelamos el objeto nulo, dado que queremos aprovechar las ventajas de la programación orientada a objeto.

Por ejemplo una acción de un comando que no haga nada:

abstract class UndoableAction(val description: String) {
def undo(): Unit
def redo(): Unit
}

object DoNothingAction extends UndoableAction("Do nothing") {
override def undo() {}
override def redo() {}
}

Luego si tenemos un mapa de acciones:

val actions = Map("open" -> DoNothingAction, "save" -> DoNothingAction, …)

El método apply

Es común que los objetos tengan un método apply que se ejecuta cuando se llama el objeto con parámetros:

Object(arg1, ..., argN)

Típicamente estos métodos retornan una instancia de la clase que acompaña este objeto.

Por ejemplo el Array tiene un método apply que construye un Array con los objetos pasados por parámetros:

Array("Mary", "had", "a", "little", "lamb")

Porque no usar un constructor? Para no usar la palabra clave new, de esta manera podemos construir  un arreglo de la siguiente manera:

Array(Array(1, 7), Array(2, 9))

Veamos un ejemplo de una definición de un método apply :

class Account private (val id: Int, initialBalance: Double) {
    private var balance = initialBalance
    ...
}
object Account { // The companion object
    def apply(initialBalance: Double) =
new Account(newUniqueNumber(), initialBalance)
   …
 }

Ahora podemos construir una cuenta de la siguiente manera:

val acct = Account(1000.0)

El Objeto aplicación

Un programa Scala al igual que c++ o java, ejecuta un método main el cual recibe por parámetros un vector de Strings y retorna el tipo Unit.

object Hello {
  def main(args: Array[String]) {
     println("Hello, World!")
  }
}

Otra forma de ejecutar programas sin escribir el método main es extender el de App :

object Hello extends App {
  println("Hello, World!")
}

Si necesita argumentos App tiene una propiedad args:

object Hello extends App {
  if (args.length > 0)
    println("Hello, " + args(0))
  else
    println("Hello, World!")
}

Ahora podemos correr nuestro programa:

$ scalac Hello.scala
$ scala Hello Fred
Hello, Fred