如何访问作为类型参数传递的Scala类的伴随对象?

时间:2018-05-30 20:51:13

标签: scala generics companion-object

我有一个带有伴侣对象的案例类:

object Taco extends Dinner[Taco] {
  def ingredientNames: Seq[String] = Seq("filling", "cheese", "sauce")
}

case class Taco(filling: Meat, cheese: Cheese, sauce: Sauce) 
extends Dinner

还有一个:

object Cheeseburger extends Dinner[Cheeseburger] {
  def ingredientNames: Seq[String] = Seq("cheese", "bun", "condiments")
}

case class CheeseBurger(cheese: Cheese, bun: Bun, condiments: Seq[Condiment]) 
extends Dinner[Cheeseburger]

在实际创建任何晚餐实例之前,我需要获取这些晚餐的成分名称:

def printMenu[D <: Dinner[D]]: String = ???

如何访问Dinner子类的伴随对象?

2 个答案:

答案 0 :(得分:2)

输入救援类:

trait Dinner { ... }
trait DinnerCompanion[A <: Dinner] {
  implicit def self: DinnerCompanion[A] = this
  def ingredientNames: Seq[String]
  ...
}

object Taco extends DinnerCompanion[Taco] {
  def ingredientNames: Seq[String] = Seq("filling", "cheese", "sauce")
}

case class Taco(filling: Meat, cheese: Cheese, sauce: Sauce) extends Dinner

def printMenu[A <: Dinner](implicit companion: DinnerCompanion[A]): String = 
  companion.ingredientNames.mkString(", ")

答案 1 :(得分:1)

您可能需要以下构造(受标准集合库中的GenericCompanion启发):

type Condiment = String
type Meat = String
type Cheese = String
type Sauce = String
type Bun = String


trait Dinner[A] {
  def companion: DinnerCompanion[A]
}

trait DinnerCompanion[A] {
  def ingredientNames: Seq[String]
}

case class Taco(filling: Meat, cheese: Cheese, sauce: Sauce) 
extends Dinner[Taco] {
  def companion = Taco
}

implicit object Taco extends DinnerCompanion[Taco] {
  def ingredientNames: Seq[String] = Seq("filling", "cheese", "sauce")
}

case class CheeseBurger(cheese: Cheese, bun: Bun, condiments: Seq[Condiment]) 
extends Dinner[CheeseBurger] {
  def companion = CheeseBurger
}

implicit object CheeseBurger extends DinnerCompanion[CheeseBurger] {
  def ingredientNames: Seq[String] = Seq("cheese", "bun", "condiments")
}

def printMenu[D: DinnerCompanion]: String = 
  implicitly[DinnerCompanion[D]].ingredientNames.mkString

现在Dinner的每个实例都有方法companion,而companion又有ingredientNames

编辑添加了printMenu(与配对对象无关,使用object Tacoobject CheeseBurger作为普通的类型类实例。)