Создать объект во время выполнения, который имеет одинаковое внутреннее содержимое - PullRequest
1 голос
/ 23 января 2020

Я выполняю повторяющуюся задачу создания объекта, который имеет такое же внутреннее содержимое, и, следовательно, подумал о создании общего c метода, который помог бы мне достичь этого.

Внутренний объект выглядит следующим образом

case class Data(value: Int)

У меня есть базовая черта следующим образом

trait Base

Есть несколько классов, которые расширяют эту черту

case class A(data: Data) extends Base
case class B(data: Data) extends Base
case class C(data: Data) extends Base

Метод generi c, который я я пытаюсь написать для создания объекта

def getObject[T <: Base](data: Data, t: T) = {
  T(data)
}

Однако, при попытке сделать это, я получаю ошибку во время компиляции, говорящую, что

Cannot resolve symbol T

Можете ли вы сообщить мне, что Мне не хватает в реализации этого метода. Примечание: - Это очень простая c реализация того, что я пытаюсь сделать в своем коде.

Ответы [ 2 ]

4 голосов
/ 23 января 2020

Из-за стирание типа вы не можете использовать тип generi c для создания нового экземпляра объекта.

Вы можете использовать ClassTag для захвата класса T во время выполнения:

case class Data(value: Int)

trait Base

case class A(data: Data) extends Base
case class B(data: Data) extends Base
case class C(data: Data) extends Base

def getObject[T <: Base](data: Data)(implicit ct: ClassTag[T]): T = 
  ct.runtimeClass.getDeclaredConstructors.head.newInstance(data).asInstanceOf[T]


val a: A = getObject[A](Data(1))
val b: B = getObject[B](Data(2))
val c: C = getObject[C](Data(3))

Как заметил cchantep, у него есть недостаток: если ваш класс case не имеет конструктора с одним аргументом Data, эта функция завершится с ошибкой во время выполнения.

2 голосов
/ 23 января 2020

Рассмотрим класс типов решение для безопасности во время компиляции

final case class Data(value: Int)
final case class A(data: Data)
final case class B(data: Data)
final case class C(data: Data)

trait BaseFactory[T] {
  def apply(data: Data): T
}

object BaseFactory {
  def apply[T](data: Data)(implicit ev: BaseFactory[T]): T = ev.apply(data)
  implicit val aBaseFactory: BaseFactory[A] = (data: Data) => A(data)
  implicit val bBaseFactory: BaseFactory[B] = (data: Data) => B(data)
  implicit val cBaseFactory: BaseFactory[C] = (data: Data) => C(data)
}

val data = Data(42)
BaseFactory[A](data)   // res0: A = A(Data(42))
BaseFactory[B](data)   // res1: B = B(Data(42)) 
BaseFactory[C](data)   // res2: C = C(Data(42))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...