5
votes

I am just going through abstract type in Scala and I got an error

The example I was trying:

scala> class Food
abstract class Animal {
type SuitableFood <: Food
def eat(food: SuitableFood)
}
defined class Food
defined class Animal

scala> class Grass extends Food
class Cow extends Animal {
type SuitableFood = Grass
override def eat(food: Grass) {}
}
defined class Grass
defined class Cow

scala> class Fish extends Food
defined class Fish

scala> val bessy: Animal = new Cow
bessy: Animal = Cow@5c404da8

scala> bessy.eat(new bessy.SuitableFood)
<console>:13: error: class type required but bessy.SuitableFood found
              bessy.eat(new bessy.SuitableFood)
                                  ^

scala> bessy.eat(bessy.SuitableFood)
<console>:13: error: value SuitableFood is not a member of Animal
              bessy.eat(bessy.SuitableFood)

scala> bessy.eat(new Grass)
<console>:13: error: type mismatch;
 found   : Grass
 required: bessy.SuitableFood
              bessy.eat(new Grass)

What are these errors?

Why can't I pass new Grass to the eat method as an argument, and when I create an object like

scala> val c=new Cow
c: Cow = Cow@645dd660


scala> c.eat(new Grass)

Could you give me some idea about this?

1

1 Answers

5
votes

When you assign bessy, you upcast the Cow instance to an Anmial:

val bessy: Animal = new Cow

So from a static point of view, bessy is an Animal and therefore bessy.SuitableFood abstract. Now to the errors:

  1. You cannot create an object of an abstract type with new.
  2. bessy.SuitableFood tries to access the value-member SuitableFood (i.e. def/val)
  3. Since bessy is "only" an Animal, you don't know (statically) if it can eat Grass.

What you can do, is add a method to Animal that allows you to create food:

abstract class Animal {
  type SuitableFood <: Food
  def eat(food: SuitableFood)
  def makeFood(): SuitableFood
}

And implement:

class Cow extends Animal {
  type SuitableFood = Grass
  override def eat(food: Grass) {}
  override def makeFood() = new Grass()
}

Now you may call (on any Animal):

bessy.eat(bessy.makeFood())