es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Devuelve el tipo concreto para un rasgo desde su objeto compañero.

Antes, devolvía tipos concretos desde un rasgo, pero nunca desde un objeto compañero de un rasgo y no pude encontrar un ejemplo de mi escenario exacto en línea. Por favor, siéntase libre de indicarme si esto es un duplicado.

Tengo este rasgo:

trait Problem[T <: ProblemInput] {
  // utiliza el patrón de plantilla llamando a métodos abstractos implementados en las implementaciones
  def solve(problemInput: T): Solution = {
    ...
  }
}

y luego algunas implementaciones de él:

class DoubleCube extends Problem[Cube] {
  ...
}

class SquareCircle extends Problem[Circle] {
  ..
}

Quiero poder tener un método de fábrica para mapear una entrada de problema a su problema, es decir:

object Problem {

def apply[T <: ProblemInput](problemInput: T): Problem[T] = input match {
    case Cube(_,_) => DoubleCube()
    case Circle(_,_) => SquareCircle()
  }
}

La solución no se compila con el siguiente error (ejemplo):

type mismatch;

found : DoubleCube

required: Problem[T]

case Cube(_,_) => DoubleCube()

Actualización
Siguiendo el consejo de @Tim: Modifiqué el código para proporcionar una clase de tipo que realizaría la traducción del mapeo, por lo que ahora la implementación se ve así:

trait Translator[T <: ProblemInput] {
  def translate(pi: ProblemInput): Problem[T]
}

object TranslatorInstances {
  implicit val forCube: Translator[Cube] = (pi: Cube) =>
    new DoubleCube()
  implicit val forCircle: Translator[Circle] = (pi: Circle) =>
    new SquareCircle()
}

object Problem {
  def apply[T <: ProblemInput](pi: ProblemInput)(implicit
    translator: Translator[T]
  ): Problem[T] = translator.translate(pi)
  ...
}

Esto se compila, pero traslada el problema al lado del llamador:

def ladoDelLlamador(pi: ProblemInput): Unit = {
  val problem = pi match {
    case Cube(_,_) => Problem[Cube]
    ...
}
  problem.solve(pi)
  ...
}

El compilador se queja de que:

type mismatch;

found : ProblemInput

required: _1

problem.solve(pi)

^

one error found
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Devolviendo Tipos Concretos desde Objetos Compañeros de Traits en Scala

    El objetivo es tener un método de factoría para mapear una entrada de problema a su problema correspondiente, es decir, crear una instancia de Problem[T] basada en una ProblemInput dada. La implementación inicial devuelve un tipo concreto desde un objeto compañero del trait, pero falla al compilar con un error de tipo incompatible.

    Una solución es proporcionar una clase de tipo que traduzca el mapeo. Creando un trait Translator[T] e instancias implícitas de ella, podemos implementar el objeto Problem con un método apply que tome una ProblemInput y un Translator[T] como parámetro implícito, y devuelva la correspondiente instancia de Problem[T].

    La solución basada en tipo de clase mantiene la lógica de mapeo centralizada en el objeto Problem y ofrece más flexibilidad ya que el traductor puede ser extendido agregando nuevas instancias implícitas de él. Sin embargo, el lado que llama será responsable de pasar el Translator[T] correcto al método apply, lo cual puede ser un poco tedioso.

    En general, devolver tipos concretos desde objetos compañeros de traits puede no ser la mejor opción de diseño, y utilizar una solución basada en tipo de clase puede proporcionar más flexibilidad y una mejor separación de responsabilidades.

Comments are closed.