Friday, October 16, 2015

Applications of bstract types in Scala

Nested polymophism might not be a good idea:

object Example {
  class Food 
  abstract class Animal {
    def eat(food: Food)
  }
  class Grass extends Food 
  class Cow extends Animal {
    override def eat(food: Grass) {} // won't compile
  }
  // suppose the Cow code successfully compiles 
  class Fish extends Food 
  val bessy: Animal = new Cow 
  bessy eat(new Fish)
}

Abstract types is helpful in this case:

object Example {
  class Food
  abstract class Animal {
    type SuitableFood <: Food
    def eat(food: SuitableFood)
  }
  class Grass extends Food
  class Cow extends Animal {
    type SuitableFood = Grass
    override def eat(food: Grass): Unit = {
      println("I eat grass!")
    }
  }
}

This is all nice, but, can’t I just use generics?

object Example {
  class Food
  abstract class Animal[F <: Food] {
    def eat(food: F)
  }
  class Grass extends Food
  class Cow extends Animal[Grass] {
    override def eat(food: Grass): Unit = {
      println("I eat grass!")
    }
  }
}

For a comparison of these two approaches, see this stackoverflow question: http://stackoverflow.com/questions/1154571/scala-abstract-types-vs-generics

0 comments: