抽象函数中的 Scala 泛型
Scala generics in an abstract function
有摘要classAnimal
。
Animal
由 Dog
和 Cow
扩展。
Animal
有一个抽象函数 copy
。在 Dog
上调用时应该 return Dog
并且在 Cow
上调用时 - Cow
.
abstract class Animal[T] {
def copy[CT <: Animal[T]] (): CT
}
class Dog[T] extends Animal[T] {
def copy = new Dog[T]()
}
这给出了一个错误。我做错了什么?
您在 Dog
中的 copy
方法与 Animal
中的 copy
方法没有相同的签名(Animal
有一个类型参数和 Dog
没有),因此 Scala 编译器认为您没有为 Dog
实现它。看起来您正在尝试解决 copy
应该 return 子类型的事实。您可以为此使用自我类型:
abstract class Animal[T] { self: T =>
def copy: T = this
}
class Dog extends Animal[Dog]
除非您对类型参数有其他想法?
在这种情况下使用 F-bounded 多态性可能更谨慎,以验证 T
是 Animal
.
的子类型
abstract class Animal[T <: Animal[T]]
本质上 CT
对于您的工作方法必须是不变的。 Dog 的具体实现无法控制 CT
的类型,例如,您的方法无法解释这一点(因此出现编译器错误):
new Dog[Int]().copy[Cow[Int]]()
你的具体实现给了我 Dog
但我想要 Cow
。这是因为您的 copy
方法不可能满足 return 类型参数方差。如果你只需要一个 return 类型用于 copy
方法,你可以使用这个替代方法(灵感来自与 C++ 中出现的相同问题):
abstract class Animal[T, SubType <: Animal[T, _]] {
def copy (): SubType
}
class Dog[T] extends Animal[T, Dog[T]] {
override def copy() = new Dog[T]
}
val animal: Animal[Int, Dog[Int]] = new Dog()
val dogCopy: Dog[Int] = animal.copy()
这是另一种更简单(不那么明显)的方法。 Scala 不仅允许您覆盖方法的实现,还允许您在某种程度上覆盖 return 类型:
abstract class Animal[T] {
def copy (): Animal[T]
}
class Dog[T] extends Animal[T] {
override def copy() = new Dog[T]
}
val dog = new Dog[Int]()
val dogCopy: Dog[Int] = dog.copy()
有摘要classAnimal
。
Animal
由 Dog
和 Cow
扩展。
Animal
有一个抽象函数 copy
。在 Dog
上调用时应该 return Dog
并且在 Cow
上调用时 - Cow
.
abstract class Animal[T] {
def copy[CT <: Animal[T]] (): CT
}
class Dog[T] extends Animal[T] {
def copy = new Dog[T]()
}
这给出了一个错误。我做错了什么?
您在 Dog
中的 copy
方法与 Animal
中的 copy
方法没有相同的签名(Animal
有一个类型参数和 Dog
没有),因此 Scala 编译器认为您没有为 Dog
实现它。看起来您正在尝试解决 copy
应该 return 子类型的事实。您可以为此使用自我类型:
abstract class Animal[T] { self: T =>
def copy: T = this
}
class Dog extends Animal[Dog]
除非您对类型参数有其他想法?
在这种情况下使用 F-bounded 多态性可能更谨慎,以验证 T
是 Animal
.
abstract class Animal[T <: Animal[T]]
本质上 CT
对于您的工作方法必须是不变的。 Dog 的具体实现无法控制 CT
的类型,例如,您的方法无法解释这一点(因此出现编译器错误):
new Dog[Int]().copy[Cow[Int]]()
你的具体实现给了我 Dog
但我想要 Cow
。这是因为您的 copy
方法不可能满足 return 类型参数方差。如果你只需要一个 return 类型用于 copy
方法,你可以使用这个替代方法(灵感来自与 C++ 中出现的相同问题):
abstract class Animal[T, SubType <: Animal[T, _]] {
def copy (): SubType
}
class Dog[T] extends Animal[T, Dog[T]] {
override def copy() = new Dog[T]
}
val animal: Animal[Int, Dog[Int]] = new Dog()
val dogCopy: Dog[Int] = animal.copy()
这是另一种更简单(不那么明显)的方法。 Scala 不仅允许您覆盖方法的实现,还允许您在某种程度上覆盖 return 类型:
abstract class Animal[T] {
def copy (): Animal[T]
}
class Dog[T] extends Animal[T] {
override def copy() = new Dog[T]
}
val dog = new Dog[Int]()
val dogCopy: Dog[Int] = dog.copy()