lunes, 24 de julio de 2017

Un resumen de Scala for the Impatient, parte 25

La herencia de jerarquías en Scala.

El siguiente gráfico muestra la jerarquía de clases en Scala. Los tipos primitivos de java extienden de AnyVal.

Las referencias a clases o subclases extienden de AnyRef, que es sinónimo de Object de java o .net.
AnyVal y AnyRef extienden de Any, el inicio de la jerarquía.

La clase Any define los métodos isInstanceOf, asInstanceOf y métodos generales como equals o hashcode.

AnyVal no agrega ningún método, solo representa el tipo de los valores.

AnyRef agrega métodos de monitoreo como wait, notify o notifyAll (que son métodos de la clase Object) , también tiene un método synchronized, el cual puede recibir como parámetro una clausura, la cual va ser ejecutada como threed safe.

Todas las clases de scala implementan la interface ScalaObject, que no tiene métodos.

En el otro extremo de la jerarquía están los tipos Nothing y Null. Null es un tipo que tiene una sola instancia null, el desarrollador puede asignar null a cualquier referencia pero no a cualquier valor. Por ejemplo no se le puede asignar null a un valor entero.

El tipo Nothing no tiene instancia, ocasionalmente es útil para constructores genéricos o por ejemplo para definir Nil (que en una lista vacía) de tipo List[Nothing]

Ojo Nothing no es igual que void de Java o C, void en scala se representa con el tipo Unit, que es un tipo que tiene un solo valor ().  Tenga en cuenta que Unit no es un supertipo de ningún otro tipo. Sin embargo, el compilador permite que Any sea reemplazado por Unit.

Igualdad de objetos

En scala, el método eq esta definido en la clase AnyRef y comprueba si dos referencias referencian al mismo objeto. El método equals en AnyRef llama eq. Cuando implemente una clase, debe considerar la posibilidad sobrescribir el método equals para proporcionar una noción natural de igualdad para los objetos.
 
Por ejemplo, si definimos class Item(val description: String, val price: Double) se debe sobrescribir el método equals como en Java:

final override def equals(other: Any) = {
val that = other.asInstanceOf[Item]
if (that == null) false
else description == that.description && price == that.price
}

Cuando defina iguales, recuerde definir también hashCode como en Java. El código de hash se debe calcular sólo a partir de los campos que se utilizan en la comprobación de igualdad. Por ejemplo:

final override def hashCode = 13 * description.hashCode + 17 * price.hashCode

Generalmente no se llama el método eq o equals. Simplemente utilice el operador ==. Para tipos de referencia, llama a equals después de hacer la comprobación adecuada para los operandos nulos.