我是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)
关于为什么代码无法编译以及如何使它起作用的任何想法?
答案 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)
}
}