Por Lucas Trubiano - Data Engineer | Profesor y Consultor

¿Por qué no hay herencia múltiple?

En Scala, no se permite la herencia múltiple de clases, lo que significa que una clase no puede heredar de múltiples clases base. En cambio, Scala utiliza traits para lograr la reutilización de código y la composición.

<aside> 💬 Un trait es una entidad que define un conjunto de miembros (métodos y campos) que pueden ser mezclados en clases. A diferencia de las clases abstractas, un trait no puede tener un constructor. Puedes pensar en un trait como una plantilla que define un conjunto de métodos y/o campos que pueden ser compartidos por múltiples clases.

</aside>

Rasgos como interfaces

Los traits en Scala son similares a las interfaces en otros lenguajes de programación. Puedes definir métodos abstractos en un trait y luego mezclar (mix-in) el trait en una clase para proporcionar implementaciones concretas.

trait Saludable {
  def saludar(): Unit
}

class Persona(nombre: String) extends Saludable {
  def saludar(): Unit = println(s"Hola, soy $nombre.")
}

val p = new Persona("Lucas")
p.saludar()

Rasgos con implementaciones concretas

En Scala, los traits pueden contener métodos con implementaciones concretas. Esto permite la reutilización de código y facilita la implementación de métodos en clases que mezclan el trait.

trait Saludable {
  def saludar(): Unit = println("¡Hola!")
}

class Persona(nombre: String) extends Saludable {
  override def saludar(): Unit = println(s"Hola, soy $nombre.")
}

val p = new Persona("Lucas")
p.saludar()

Objetos con rasgos

Los objetos en Scala pueden mezclar traits para extender sus funcionalidades. Esto permite crear objetos con características específicas.

object MiApp extends Saludable {
  def main(args: Array[String]): Unit = {
    saludar()
  }
}

Rasgos en capas

Puedes mezclar múltiples traits en una misma clase o objeto, creando capas de funcionalidad. Esto facilita la composición de comportamientos.

trait A {
  def mensajeA: String = "Mensaje de A"
}

trait B {
  def mensajeB: String = "Mensaje de B"
}

class C extends A with B {
  def mensajeC: String = "Mensaje de C"
}

Anulación de métodos abstractos en rasgos

Si un trait define un método abstracto y otro trait lo hereda, la clase que mezcla ambos traits debe proporcionar una implementación para el método.

trait Saludable {
  def saludar(): Unit
}

trait Mensajero extends Saludable {
  def mensaje: String
  def saludar(): Unit = println(mensaje)
}