-
-
Save joprice/ce4d9f000c285f602aff to your computer and use it in GitHub Desktop.
Abstract Type vs Type parameter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait AnimalMouth | |
class Beak extends AnimalMouth | |
object Test1 { | |
//================================Generic type works as in the following ======================= | |
trait Animal[Mouth <: AnimalMouth] { | |
def mouth : Mouth | |
def feedAnother(m: Mouth): Unit = () | |
} | |
class Bird extends Animal[Beak] { | |
def mouth: Beak = new Beak | |
} | |
// compiles, but when called with two instances of Bird, gives `type arguments [Mouth] do not conform to trait Animal's type parameter bounds [Mouth <: AnimalMouth]` | |
//def feed[Mouth <: AnimalMouth, A <: Animal[Mouth]](mother: A, child: A) : Unit = mother.feedAnother(child.mouth) | |
def feed[Mouth <: AnimalMouth](mother: Animal[Mouth], child: Animal[Mouth]): Unit = mother.feedAnother(child.mouth) | |
} | |
//==============Make mouth an abstract type and it would be hard =========================== | |
object Test2 { | |
trait Animal { | |
type Mouth <: AnimalMouth | |
def mouth : Mouth | |
def feedAnother(m: Mouth): Unit = () | |
} | |
class Bird extends Animal { | |
type Mouth = Beak | |
def mouth: Mouth = new Beak | |
} | |
def feed[A <: Animal, B](mother: A { type Mouth = B}, child: A {type Mouth = B} ) : Unit = mother.feedAnother(child.mouth) | |
} | |
//=============== Work Around using Aux ================ | |
object Test3 { | |
trait Animal { | |
type Mouth <: AnimalMouth | |
def mouth : Mouth | |
def feedAnother(m: Mouth): Unit = () | |
} | |
class Bird extends Animal { | |
type Mouth = Beak | |
def mouth: Mouth = new Beak | |
} | |
object Animal { | |
type Aux[Mouth0] = Animal { type Mouth = Mouth0 } | |
} | |
def feed[Mouth](mother: Animal.Aux[Mouth], child: Animal.Aux[Mouth]) : Unit = mother feedAnother child.mouth | |
} | |
object Test { | |
def main(args: Array[String]): Unit = { | |
{ | |
import Test1._ | |
val mother = new Bird() | |
val child = new Bird() | |
feed(mother, child) | |
} | |
{ | |
import Test2._ | |
val mother = new Bird() | |
val child = new Bird() | |
feed(mother, child) | |
} | |
{ | |
import Test3._ | |
val mother = new Bird() | |
val child = new Bird() | |
feed(mother, child) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment