Structural types in scala

If I have a class like this

class CanFlyType[T <: {type thing <: Bird}](t : T) {
  def flySpeed() = {
    println(t)
  }
}

What can you pass in the constructor to create this class? I tried passing this

class Species
class Animal extends Species
class Tiger extends Animal
abstract class Bird (name : String) extends Species {
  val birdName = name
  val flySpeed : Int
}

class Sparrow(name : String) extends Bird(name) {
  val flySpeed = 30
}


val sparrow : Bird1 = new Sparrow("Robbin")

val canFly = new CanFlyType(sparrow)

But I get an error. I know we can achieve this in other ways, but I just want to know if you can use type in a structural type way and the difference between the above and

class CanFly1[T <: Bird1](bird : T) {
  def flySpeed() = {
    println(bird.flySpeed)
  }
}

1 answer

  • answered 2018-11-08 07:32 Norwæ

    When you specify [T <: {type thing <: Bird}], you are telling the compiler to look for a type with a type member called thing, which itself must be a subclass of Bird.

    The following fixes the issue:

    class Species
    class Animal extends Species
    class Tiger extends Animal
    abstract class Bird (name : String) extends Species {
      val birdName = name
      val flySpeed : Int
    }
    
    class Sparrow(name : String) extends Bird(name) {
      type thing = this.type
      val flySpeed = 30
    }
    
    
    val sparrow : Sparrow = new Sparrow("Robbin")
    
    val canFly = new CanFlyType(sparrow)
    
    class CanFlyType[T <: {type thing <: Bird}](t : T) {
      def flySpeed() = {
        println(t)
      }
    }
    

    Note that is probably NOT what you want to do in practice. You probably are looking to simply simply constrain your CanFlyType[T <: Bird].