Reputation: 3130
I have a case class with 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
And another one:
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]
I need to get ingredient names for these dinners before actually creating any dinner instances:
def printMenu[D <: Dinner[D]]: String = ???
How can I access the companion object of a Dinner
subclass?
Upvotes: 1
Views: 1259
Reputation: 44918
You probably want the following construction (inspired by GenericCompanion
from the standard collection library):
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
Now every instance of a Dinner
has method companion
, and the companion
in turn has ingredientNames
.
EDIT added printMenu
(has nothing to do with companion objects whatsoever, uses object Taco
and object CheeseBurger
as ordinary typeclass instances).
Upvotes: 1
Reputation: 170723
Type classes to the rescue:
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(", ")
Upvotes: 4