En aquest tema, explorarem dos conceptes fonamentals de la programació orientada a objectes en Scala: l'herència i els traits. Aquests conceptes permeten la reutilització de codi i la creació de jerarquies de classes més flexibles i modulars.

  1. Herència en Scala

L'herència és un mecanisme que permet a una classe derivar-se d'una altra classe, heretant-ne els camps i mètodes. Això facilita la reutilització de codi i la creació de jerarquies de classes.

1.1. Definició de Classes Base i Derivades

En Scala, una classe base es defineix de manera similar a altres llenguatges orientats a objectes. Una classe derivada s'especifica utilitzant la paraula clau extends.

// Definició de la classe base
class Animal {
  def makeSound(): Unit = {
    println("Some generic animal sound")
  }
}

// Definició de la classe derivada
class Dog extends Animal {
  override def makeSound(): Unit = {
    println("Bark")
  }
}

// Exemple d'ús
val myDog = new Dog()
myDog.makeSound()  // Output: Bark

1.2. Sobreescriptura de Mètodes

En Scala, els mètodes de la classe base poden ser sobreescrits a la classe derivada utilitzant la paraula clau override.

class Cat extends Animal {
  override def makeSound(): Unit = {
    println("Meow")
  }
}

val myCat = new Cat()
myCat.makeSound()  // Output: Meow

1.3. Constructors i Herència

Els constructors de la classe base poden ser invocats des de la classe derivada utilitzant la sintaxi de constructors.

class Animal(val name: String) {
  def makeSound(): Unit = {
    println(s"$name makes a sound")
  }
}

class Bird(name: String) extends Animal(name) {
  override def makeSound(): Unit = {
    println(s"$name chirps")
  }
}

val myBird = new Bird("Parrot")
myBird.makeSound()  // Output: Parrot chirps

  1. Traits en Scala

Els traits són una característica poderosa de Scala que permet la reutilització de codi de manera més flexible que les classes abstractes. Un trait és similar a una interfície en altres llenguatges, però pot contenir implementacions de mètodes.

2.1. Definició de Traits

Un trait es defineix utilitzant la paraula clau trait.

trait Swimmable {
  def swim(): Unit = {
    println("Swimming")
  }
}

class Fish extends Swimmable

val myFish = new Fish()
myFish.swim()  // Output: Swimming

2.2. Implementació de Múltiples Traits

Una classe pot implementar múltiples traits utilitzant la paraula clau with.

trait Flyable {
  def fly(): Unit = {
    println("Flying")
  }
}

class Duck extends Swimmable with Flyable

val myDuck = new Duck()
myDuck.swim()  // Output: Swimming
myDuck.fly()   // Output: Flying

2.3. Sobreescriptura de Mètodes en Traits

Els mètodes dels traits poden ser sobreescrits de manera similar als mètodes de les classes.

trait Runnable {
  def run(): Unit = {
    println("Running")
  }
}

class Cheetah extends Runnable {
  override def run(): Unit = {
    println("Running fast")
  }
}

val myCheetah = new Cheetah()
myCheetah.run()  // Output: Running fast

Exercicis Pràctics

Exercici 1: Herència Bàsica

Crea una classe base Vehicle amb un mètode move(). Després, crea una classe derivada Car que sobreescrigui el mètode move() per imprimir "Driving".

class Vehicle {
  def move(): Unit = {
    println("Moving")
  }
}

class Car extends Vehicle {
  override def move(): Unit = {
    println("Driving")
  }
}

val myCar = new Car()
myCar.move()  // Output: Driving

Exercici 2: Implementació de Traits

Defineix dos traits, Flyable i Swimmable, cadascun amb un mètode corresponent. Crea una classe Duck que implementi ambdós traits i crida els mètodes fly() i swim().

trait Flyable {
  def fly(): Unit = {
    println("Flying")
  }
}

trait Swimmable {
  def swim(): Unit = {
    println("Swimming")
  }
}

class Duck extends Flyable with Swimmable

val myDuck = new Duck()
myDuck.fly()   // Output: Flying
myDuck.swim()  // Output: Swimming

Resum

En aquest tema, hem après sobre l'herència i els traits en Scala. Hem vist com les classes poden heretar d'altres classes, com sobreescriure mètodes i com utilitzar constructors en herència. També hem explorat els traits, que permeten la reutilització de codi de manera més flexible que les classes abstractes, i hem vist com implementar múltiples traits en una sola classe. Aquests conceptes són fonamentals per a la programació orientada a objectes en Scala i proporcionen una base sòlida per a la creació de codi modular i reutilitzable.

© Copyright 2024. Tots els drets reservats