En aquest tema, explorarem dos conceptes avançats de Scala: les classes de tipus i el polimorfisme. Aquests conceptes són fonamentals per escriure codi flexible i reutilitzable en Scala.

Classes de Tipus

Les classes de tipus són una característica poderosa de Scala que permet definir comportaments genèrics per a diferents tipus de dades. Això es fa mitjançant la definició de traits que especifiquen un conjunt de funcions que han de ser implementades per qualsevol tipus que vulgui ser una instància d'aquesta classe de tipus.

Definició d'una Classe de Tipus

Comencem amb un exemple senzill. Suposem que volem definir una classe de tipus Show que proporciona una manera de convertir qualsevol tipus a una cadena (String).

trait Show[T] {
  def show(value: T): String
}

Implementació d'Instàncies de la Classe de Tipus

Ara, implementem instàncies de la classe de tipus Show per a alguns tipus comuns.

implicit val intShow: Show[Int] = new Show[Int] {
  def show(value: Int): String = value.toString
}

implicit val stringShow: Show[String] = new Show[String] {
  def show(value: String): String = value
}

Ús de la Classe de Tipus

Podem definir una funció genèrica que utilitzi la classe de tipus Show per mostrar qualsevol valor.

def printValue[T](value: T)(implicit s: Show[T]): Unit = {
  println(s.show(value))
}

printValue(123)    // Output: 123
printValue("Hola") // Output: Hola

Exercici Pràctic

Exercici: Defineix una classe de tipus Equal que proporciona una manera de comparar dos valors per igualtat. Implementa instàncies per als tipus Int i String.

trait Equal[T] {
  def equal(a: T, b: T): Boolean
}

implicit val intEqual: Equal[Int] = new Equal[Int] {
  def equal(a: Int, b: Int): Boolean = a == b
}

implicit val stringEqual: Equal[String] = new Equal[String] {
  def equal(a: String, b: String): Boolean = a == b
}

def areEqual[T](a: T, b: T)(implicit eq: Equal[T]): Boolean = {
  eq.equal(a, b)
}

// Prova els teus resultats
println(areEqual(10, 10))    // Output: true
println(areEqual(10, 20))    // Output: false
println(areEqual("Scala", "Scala")) // Output: true
println(areEqual("Scala", "Java"))  // Output: false

Polimorfisme

El polimorfisme és la capacitat de tractar objectes de diferents tipus de manera uniforme. Scala suporta diversos tipus de polimorfisme, incloent el polimorfisme ad-hoc (mitjançant classes de tipus) i el polimorfisme paramètric.

Polimorfisme Paramètric

El polimorfisme paramètric permet definir funcions i classes que poden operar sobre qualsevol tipus. Això es fa mitjançant l'ús de paràmetres de tipus.

def identity[T](x: T): T = x

println(identity(42))       // Output: 42
println(identity("Scala"))  // Output: Scala

Polimorfisme Ad-hoc

El polimorfisme ad-hoc es refereix a la capacitat de definir comportaments específics per a diferents tipus mitjançant classes de tipus, com hem vist anteriorment.

Exercici Pràctic

Exercici: Defineix una funció genèrica compare que utilitzi la classe de tipus Equal per comparar dos valors de qualsevol tipus.

def compare[T](a: T, b: T)(implicit eq: Equal[T]): Boolean = {
  eq.equal(a, b)
}

// Prova els teus resultats
println(compare(10, 10))    // Output: true
println(compare(10, 20))    // Output: false
println(compare("Scala", "Scala")) // Output: true
println(compare("Scala", "Java"))  // Output: false

Resum

En aquesta secció, hem après sobre les classes de tipus i el polimorfisme en Scala. Les classes de tipus ens permeten definir comportaments genèrics per a diferents tipus de dades, mentre que el polimorfisme ens permet tractar objectes de diferents tipus de manera uniforme. Aquests conceptes són fonamentals per escriure codi flexible i reutilitzable en Scala.

En el següent tema, explorarem els macros i la reflexió en Scala, que ens permetran escriure codi més dinàmic i potent.

© Copyright 2024. Tots els drets reservats