具有通用方法的Scala抽象通用类未编译

时间:2018-09-19 16:42:51

标签: scala

我是Scala的新手,我尝试了解通用抽象类/方法的工作原理

下面的代码无法编译,从错误消息看来,覆盖抽象的方法的参数不是作为类参数的类型

abstract class Pet(someString: String) {
    def name: String
}

class Cat(someString: String) extends Pet(someString) {
    val name = someString;
}

class Dog(someString: String) extends Pet(someString) {
    val name = someString;
}


abstract class Printer[+A] {
    def print[B >: A](printableObject: B): Unit
}

class CatPrinter extends Printer[Cat] {

    override def print[B >: Cat](cat: B): Unit = println("the cat name is: " + cat.name)
}
class DogPrinter extends Printer[Dog] {

    override def print[B >: Dog](dog: B): Unit = println("the dog name is: " + dog.name)
}


object Test {

    val myCat: Cat = new Cat("Booster")

    def printMyCat(printer: Printer[Pet]): Unit = {
        printer.print(myCat)
    }

    def main(args: Array[String]): Unit = {
        val catPrinter = new CatPrinter
        val dogPrinter = new DogPrinter

        printMyCat(catPrinter)
        printMyCat(dogPrinter)
    }
}

编译失败,并显示以下消息

ScalaFiddle.scala:20: error: value name is not a member of type parameter B&0
    override def print[B >: Cat](cat: B): Unit = println("the dog name is: " + cat.name)
                                                                                       ^
ScalaFiddle.scala:24: error: value name is not a member of type parameter B&0
    override def print[B >: Dog](dog: B): Unit = println("the dog name is: " + dog.name)

关于为什么代码无法编译以及如何使它起作用的任何想法?

1 个答案:

答案 0 :(得分:1)

但是,当您编写def print[B >: A](printableObject: B): Unit时,则意味着该方法接受A及其所有父母(包括Any)。 Any没有name属性。

要解决此问题,您应该将上限类型设置为Pet

abstract class PetPrinter[+A <: Pet] {
    def print[B >: A <: Pet](printableObject: B): Unit
}
class CatPrinter extends Printer[Cat] {
    override def print[B >: Cat <: Pet](cat: B): Unit = println(s"the cat name is: ${cat.name}")
}
class DogPrinter extends Printer[Dog] {
    override def print[B >: Dog <: Pet](dog: B): Unit = println(s"the dog name is: ${dog.name}")
}

但是我认为最好这样写:

abstract class Pet(someString: String) {
  def name: String
}
class Cat(someString: String) extends Pet(someString) {
  override val name = someString
}
class Dog(someString: String) extends Pet(someString) {
    override val name = someString
}
class PetPrinter[-A <: Pet] {
    def print(printableObject: A): Unit = println(s"the pet name is: ${printableObject.name}")
}
object Test {
    def printPet[T <: Pet](pet: T, printer: PetPrinter[T]): Unit = {
        printer.print(pet)
    }

    def main(args: Array[String]): Unit = {
        val cat: Cat = new Cat("Cat")
        val dog: Dog = new Dog("Dog")

        val petPrinter = new PetPrinter[Pet]
        val catPrinter = new PetPrinter[Cat]

        printPet(cat, petPrinter)
        printPet(cat, catPrinter)
        printPet(dog, petPrinter)
    }
}