martes, 20 de junio de 2017

Un resumen de Scala for the Impatient, parte 22


Extender una Clase. 

Se puede extender una clase con la palabra extends :
class Employee extends Person {
var salary = 0.0

}

Como en Java, en la subclase se pueden agregar atributos y métodos y sobre escribir métodos existentes de la super clases.

Igual que Java, se pueden marcar las clases como final y no van a poder ser extendidas pero en scala se agrega que un método o atributo pueden ser final.

Sobre escribir métodos. 

En scala se debe utilizar el modificador override cuando se sobre escribe un método y este no es abstracto. Por ejemplo:

public class Person {

override def toString = getClass.getName + "[name=" + name + "]"
}

El modificador override es muy útil para encontrar errores muy comunes como los siguientes:

  • Cuando se escribe mal el método que quiero sobre escribir
  • Cuando se agrega un parámetro de más o de menos, y no tiene la misma firma. 
  • Cuando se modifica el método padre en la super clase.


Si se desea llamar a un método del padre se hace igual que java se llama por medio de la palabra clave super.

public class Employee extends Person {

override def toString = super.toString + "[salary=" + salary + "]"
}

Al llamar a super.toString se esta llamando a el método toString de la clase Person.

Chequeo de tipos y casteos. 

El desarrollador puede saber si un objeto es de una clase determinada con el método isInstanceOf. Si esta clase es de un método determinado se puede castear utilizando asInstanceOf, veamos un ejemplo:

if (p.isInstanceOf[Employee]) {
val s = p.asInstanceOf[Employee] // s has type Employee

}

isInstanceOf retorna si un objeto es de una clase y  asInstanceOf hace el casteo.

Si p es null, isInstanceOf retorna false y asInstanceOf retorna null.

Si p no es un objeto Employee, asInstanceOf lanza una excepción.

Si es necesario saber que p es un empleado pero no una subclase de empleado lo hacemos de este modo:

if (p.getClass == classOf[Employee])

La función classOf esta definido en scala.Predef que siempre es importado.

A continuación se muestra una comparación con formas de chequeo de java:

Scala Java
obj.isInstanceOf[Cl]
obj instanceof Cl
obj.asInstanceOf[Cl]
(Cl) obj
classOf[Cl]
Cl.class

A la vez el pattern matching es útil para saber los tipos:

p match {
case s: Employee => ... // Hacer cosas con el empleado
case _ => ... // p no es un empleado
}

Atributos y métodos protegidos

Como en java o c++ en scala existe los atributos o métodos protegidos, que son los que puede ver la clase y sus descendientes y no por otras clases.

Pero al contrario de java estos atributos no son visibles para los objetos de su paquete.

Constructor de la super clase.

Como recordaran existe un constructor principal de la clase y pueden existir n constructores auxiliares y que todos los constructores auxiliares llaman al constructor principal.

Como consecuencia de esto un constructor auxiliar no puede invocar a un constructor auxiliar de la super clase directamente.

El constructor auxiliares de la subclase deben llamar al constructor principal de la subclase y solo el constructor principal puede llamar al constructor principal de la super clase.

El constructor principal está relacionado con la definición de clase. La llamada al constructor de la superclase está igualmente relacionado. Veamos un ejemplo:

class Employee(name: String, age: Int, val salary : Double) extends
Person(name, age)

y el primer constructor llama al constructor de la super clase.

Note que el código es sumamente conciso y  podemos pensar a nuestro constructor principal con la mayoría de los datos y los auxiliares al llamarlo pondrán valores por defecto.

Una clase Scala puede extender de una clase java. Por ejemplo:

class Square(x: Int, y: Int, width: Int) extends
java.awt.Rectangle(x, y, width, width)