Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>There aren't any useful super types to which <code>Ferrari</code> and <code>Mustang</code> can be aliased. You need to wrap the world inside out with this approach.</p> <p>One possibility is to add the <code>Garage</code> construction as a method to <code>Car</code>.</p> <p>Another possibility is to define some 'world' which takes care of producing compatible cars and garages:</p> <pre><code>trait World { type CarType &lt;: Car[CarType] def newCar() : CarType def newGarage(cars: Seq[CarType]) = new ConcreteGarage[CarType](cars) } class FerrariWorld extends World { type CarType = Ferrari def newCar() = new Ferrari(Benzin()) } class FordWorld extends World { type CarType = Mustang def newCar() = new Mustang(Benzin()) } def play(world: World) { val car = world.newCar() println(car) val gar = world.newGarage(Seq(car)) println(gar) } def test(likesFord: Boolean) { val w = if(likesFord) new FordWorld else new FerrariWorld play(w) } test(true) test(false) </code></pre> <hr> <p>You can see that this can get quite claustrophobic. So it really depends on your target scenario. Path-dependent types always cause future constraints. Consider this rather simple variant with type parameters instead:</p> <pre><code>trait Fuel { def liters: Int } trait Make { def color: String } case class Benzin(liters: Int = 0) extends Fuel case class Diesel(liters: Int = 0) extends Fuel case class Ferrari(color: String) extends Make case class Mustang(color: String) extends Make { def race() { println( "Rrrroar" )}} case class Car[M &lt;: Make, F &lt;: Fuel](make: M, fuel: F) { def refuel(f: F): Car[M, F] = copy(make, f) } case class Garage[M &lt;: Make](cars: Seq[Car[M,_]] = Seq.empty) { def add(c: Car[M,_]) = copy(cars :+ c) def remove(c: Car[M,_]) = copy(cars.filterNot(_ == c)) def refuel[F &lt;: Fuel](c: Car[M,F], f: F) = copy( cars.map { case `c` =&gt; c.refuel(f) case other =&gt; other }) } val g0 = Garage[Mustang]() val m = Car(Mustang("black"), Benzin()) val f = Car(Ferrari("red"), Benzin()) val g1 = g0.add(f) // forbidden val g1 = g0.add(m) // ok val g2 = g1.refuel(f, Benzin(45)) // forbidden val g2 = g1.refuel(m, Diesel(45)) // forbidden val g2 = g1.refuel(m, Benzin(45)) // ok g2.cars.foreach(_.make.race()) // ok </code></pre> <hr> <p>Conclusion: Don't get side-tracked...</p> <p><img src="https://i.stack.imgur.com/ExPn7.jpg" alt="enter image description here"></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload