Introducción

En este tema, exploraremos dos conceptos fundamentales en Scala: las clases abstractas y las clases caso. Ambos son componentes esenciales de la programación orientada a objetos en Scala y proporcionan herramientas poderosas para modelar datos y comportamientos.

Clases Abstractas

¿Qué es una Clase Abstracta?

Una clase abstracta es una clase que no puede ser instanciada directamente. Se utiliza para definir una estructura base que otras clases pueden extender. Las clases abstractas pueden contener métodos abstractos (sin implementación) y métodos concretos (con implementación).

Sintaxis de una Clase Abstracta

abstract class Animal {
  def makeSound(): Unit // Método abstracto
  def sleep(): Unit = { // Método concreto
    println("Sleeping...")
  }
}

Ejemplo Práctico

abstract class Animal {
  def makeSound(): Unit
  def sleep(): Unit = {
    println("Sleeping...")
  }
}

class Dog extends Animal {
  def makeSound(): Unit = {
    println("Woof!")
  }
}

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

val dog = new Dog()
dog.makeSound() // Output: Woof!
dog.sleep()     // Output: Sleeping...

val cat = new Cat()
cat.makeSound() // Output: Meow!
cat.sleep()     // Output: Sleeping...

Explicación del Código

  1. Definición de la Clase Abstracta Animal:

    • makeSound(): Método abstracto que debe ser implementado por las clases que extienden Animal.
    • sleep(): Método concreto con una implementación predeterminada.
  2. Clases Dog y Cat:

    • Ambas clases extienden Animal y proporcionan una implementación para el método makeSound().
  3. Instanciación y Uso:

    • Creamos instancias de Dog y Cat y llamamos a sus métodos makeSound() y sleep().

Clases Caso

¿Qué es una Clase Caso?

Las clases caso (case classes) son una característica especial de Scala que facilita la creación de clases inmutables y con soporte integrado para la comparación estructural, la descomposición mediante coincidencia de patrones y la copia.

Sintaxis de una Clase Caso

case class Person(name: String, age: Int)

Ejemplo Práctico

case class Person(name: String, age: Int)

val person1 = Person("Alice", 30)
val person2 = Person("Bob", 25)

// Comparación estructural
println(person1 == person2) // Output: false

// Copia con modificación
val person3 = person1.copy(age = 31)
println(person3) // Output: Person(Alice,31)

// Coincidencia de patrones
person1 match {
  case Person(name, age) => println(s"Name: $name, Age: $age")
}

Explicación del Código

  1. Definición de la Clase Caso Person:

    • name y age son parámetros del constructor y se convierten automáticamente en propiedades inmutables de la clase.
  2. Instanciación y Uso:

    • Creamos instancias de Person (person1 y person2).
    • Utilizamos la comparación estructural para verificar si person1 y person2 son iguales.
    • Usamos el método copy para crear una nueva instancia de Person basada en person1 pero con una edad diferente.
    • Aplicamos la coincidencia de patrones para descomponer person1 y extraer sus propiedades.

Ejercicios Prácticos

Ejercicio 1: Clases Abstractas

Instrucciones: Define una clase abstracta Shape con un método abstracto area() y un método concreto describe(). Luego, crea dos clases que extiendan Shape: Circle y Rectangle, implementando el método area() para cada una.

abstract class Shape {
  def area(): Double
  def describe(): Unit = {
    println("This is a shape.")
  }
}

class Circle(val radius: Double) extends Shape {
  def area(): Double = {
    Math.PI * radius * radius
  }
}

class Rectangle(val width: Double, val height: Double) extends Shape {
  def area(): Double = {
    width * height
  }
}

// Prueba tus clases
val circle = new Circle(5)
println(circle.area()) // Output: 78.53981633974483
circle.describe()      // Output: This is a shape.

val rectangle = new Rectangle(4, 5)
println(rectangle.area()) // Output: 20.0
rectangle.describe()      // Output: This is a shape.

Ejercicio 2: Clases Caso

Instrucciones: Define una clase caso Book con propiedades title, author y year. Crea una instancia de Book y utiliza la coincidencia de patrones para extraer y mostrar sus propiedades.

case class Book(title: String, author: String, year: Int)

val book = Book("1984", "George Orwell", 1949)

book match {
  case Book(title, author, year) => println(s"Title: $title, Author: $author, Year: $year")
}
// Output: Title: 1984, Author: George Orwell, Year: 1949

Conclusión

En esta sección, hemos aprendido sobre las clases abstractas y las clases caso en Scala. Las clases abstractas nos permiten definir estructuras base que otras clases pueden extender, mientras que las clases caso facilitan la creación de clases inmutables con soporte integrado para la comparación estructural y la coincidencia de patrones. Estos conceptos son fundamentales para la programación orientada a objetos en Scala y proporcionan herramientas poderosas para modelar datos y comportamientos de manera eficiente.

En el próximo tema, exploraremos los objetos compañeros y cómo se utilizan en Scala para definir métodos y propiedades estáticas.

© Copyright 2024. Todos los derechos reservados