通用协变量类带有上类型边界缺点
Scala建议在通用类中使用协方差解决方案[+T]解决方差问题,当我深入研究时,我可以产生两种解决方案,事实是,每个解决方案都有其自己的劣势。
解决方案1-例如,在类标头和方法中使用上层类型边界。
class Animal(val name: String)
class Dog(override val name: String, val property: String) extends Animal(name)
class Puppy(override val name: String, override val property: String, val age: Int) extends Dog(name, property)
abstract class AnimalCage[+A <: Animal] {
def head: A
def tail: AnimalCage[A]
def add[A <: Animal](animal: A): AnimalCage[Animal]
}
class RealCage[+A <: Animal](h: A, t: AnimalCage[A]) extends AnimalCage[A] {
override def head: A = h
override def tail: AnimalCage[A] = t
override def add[A <: Animal](animal: A): AnimalCage[Animal] = new RealCage(animal, this)
}
object EmptyCage extends AnimalCage[Nothing] {
override def head: Nothing = throw new NoSuchElementException()
override def tail: AnimalCage[Nothing] = throw new NoSuchElementException()
override def add[A <: Animal](animal: A): AnimalCage[Animal] = new RealCage(animal, this)
}
val dog1: Dog = new Dog("dog_1", "bark bark")
val dogCage: RealCage[Dog] = new RealCage(dog1, EmptyCage)
val puppy1: Puppy = new Puppy("puppy_1", "puppy bark", 5)
val x: AnimalCage[Dog] = dogCage.add(puppy1) //error! must be Animal, could not be Dog!
优点 - [动物]是更高的超级式笼子可以保持
缺点 - 当我将[Puppy]([狗]的子类型)添加到[狗]的笼子中时,我不能有[狗]的笼子而是[动物]的笼子。
解决方案2-仅在方法签名
abstract class AnyCage[+A] {
def head: A
def tail: AnyCage[A]
def add[B >: A](animal: B): AnyCage[B]
}
class RealCage[+A](h: A, t: AnyCage[A]) extends AnyCage[A] {
override def head: A = h
override def tail: AnyCage[A] = t
override def add[B >: A](animal: B): AnyCage[B] = new RealCage(animal, this)
}
object EmptyCage extends AnyCage[Nothing] {
override def head: Nothing = throw new NoSuchElementException()
override def tail: AnyCage[Nothing] = throw new NoSuchElementException()
override def add[B >: Nothing](animal: B): AnyCage[B] = new RealCage(animal, this)
}
val dog1: Dog = new Dog("dog_2", "bark bark")
val dogCage: AnyCage[Dog] = new RealCage(dog1, EmptyCage)
val bug: LivingCreature = new LivingCreature("bug")
val generalCage: AnyCage[Any] = dogCage.add(bug) // compiled but we lose all properties due to the fact the [Any] is lowest super-type.
专业人士中使用边界 - 当我将[puppy]([狗]的子类型)添加到[狗]的笼子中时,我会得到[狗]的笼子,而不是[动物]以前的解决方案。
缺点 - 我们对任何挂盘没有限制[+a],即使它与动物无关,我们也可以添加任何类型,然后较低的超级型将导致我们失去所有的所有类型[动物]的特性。
因此,问题是,是否有任何方法可以将上述两个解决方案结合起来,然后做类似的事情 -
abstract class AnimalCage[+A <: Animal] {
def head: A
def tail: AnimalCage[A]
override def add[A <: B <: Animal](animal: B): AnimalCage[B] = new RealCage(animal, this)
}
即,当我们俩都可以对笼子(&lt;:andial)限制并获得最低的超级型(不是[动物) ]但是[狗])在一种情况下,我们想在[狗]的笼子中添加一个[小狗]。
谢谢
Scala suggests using the covariance solution [+T] for the variance problem in generic class, and when I dig into it I could produce two solutions, the thing is that each one of them has its own disadvantage.
Solution 1 - using upper type boundary both in the class header and in the method, for example.
class Animal(val name: String)
class Dog(override val name: String, val property: String) extends Animal(name)
class Puppy(override val name: String, override val property: String, val age: Int) extends Dog(name, property)
abstract class AnimalCage[+A <: Animal] {
def head: A
def tail: AnimalCage[A]
def add[A <: Animal](animal: A): AnimalCage[Animal]
}
class RealCage[+A <: Animal](h: A, t: AnimalCage[A]) extends AnimalCage[A] {
override def head: A = h
override def tail: AnimalCage[A] = t
override def add[A <: Animal](animal: A): AnimalCage[Animal] = new RealCage(animal, this)
}
object EmptyCage extends AnimalCage[Nothing] {
override def head: Nothing = throw new NoSuchElementException()
override def tail: AnimalCage[Nothing] = throw new NoSuchElementException()
override def add[A <: Animal](animal: A): AnimalCage[Animal] = new RealCage(animal, this)
}
val dog1: Dog = new Dog("dog_1", "bark bark")
val dogCage: RealCage[Dog] = new RealCage(dog1, EmptyCage)
val puppy1: Puppy = new Puppy("puppy_1", "puppy bark", 5)
val x: AnimalCage[Dog] = dogCage.add(puppy1) //error! must be Animal, could not be Dog!
pros - [Animal] is the higher super-class Cage can holds
cons - When I'm adding [Puppy] (sub-type of [Dog]) to a Cage of [Dog] I can't have Cage of [Dog] but rather Cage of [Animal].
solution 2 - using boundary only in method signature
abstract class AnyCage[+A] {
def head: A
def tail: AnyCage[A]
def add[B >: A](animal: B): AnyCage[B]
}
class RealCage[+A](h: A, t: AnyCage[A]) extends AnyCage[A] {
override def head: A = h
override def tail: AnyCage[A] = t
override def add[B >: A](animal: B): AnyCage[B] = new RealCage(animal, this)
}
object EmptyCage extends AnyCage[Nothing] {
override def head: Nothing = throw new NoSuchElementException()
override def tail: AnyCage[Nothing] = throw new NoSuchElementException()
override def add[B >: Nothing](animal: B): AnyCage[B] = new RealCage(animal, this)
}
val dog1: Dog = new Dog("dog_2", "bark bark")
val dogCage: AnyCage[Dog] = new RealCage(dog1, EmptyCage)
val bug: LivingCreature = new LivingCreature("bug")
val generalCage: AnyCage[Any] = dogCage.add(bug) // compiled but we lose all properties due to the fact the [Any] is lowest super-type.
pros - When I'm adding [Puppy] (sub-type of [Dog]) to a Cage of [Dog], I get Cage of [Dog] and not [Animal] like the previous solution.
cons - we don't have restrictions on AnyCage[+A] and we can potentially add any type, even if it's not related to Animal, and then the lower super-type would be [Any] which will cause us to lose all the properties of [Animal].
Therefore, the question is, if there is any way to combine the above two solution and do something like -
abstract class AnimalCage[+A <: Animal] {
def head: A
def tail: AnimalCage[A]
override def add[A <: B <: Animal](animal: B): AnimalCage[B] = new RealCage(animal, this)
}
i.e, when we both can have restrictions on Cage (<: Animal) and also receive the lowest super-type (not [Animal] but [Dog]) in a case we want to add a [Puppy] to a Cage of [Dog].
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这两个都会做 -
谢谢路易斯
That'll do them both -
Thanks Luis