scala下界和上界
在这里,我可以向append函数添加任何我可以添加的对象,我可以看到结果类型被降级为最低公分母scala下界和上界,scala,generics,Scala,Generics,在这里,我可以向append函数添加任何我可以添加的对象,我可以看到结果类型被降级为最低公分母 但我希望具有与java相同的行为,比如def append[?super T](x:U)//这里append函数将接受T的超类型的所有对象,我如何在scala中实现类似的行为(实现super并扩展java之类的泛型)我不明白为什么要限制此操作,或者为什么返回更通用的新不可变对象会给您带来问题 但如果您不希望出现这种差异,只需删除所有差异注释: class Queue[+T]( private
但我希望具有与java相同的行为,比如def append[?super T](x:U)//这里append函数将接受T的超类型的所有对象,我如何在scala中实现类似的行为(实现super并扩展java之类的泛型)我不明白为什么要限制此操作,或者为什么返回更通用的新不可变对象会给您带来问题 但如果您不希望出现这种差异,只需删除所有差异注释:
class Queue[+T](
private val leading: List[T],
private val trailing: List[T]
) {
def append[U >: T](x: U) =
new Queue[U](leading, x :: trailing) // ...
}
class Fruit
class oranges extends Fruit
class apple extends Fruit
class diffAppale
val q1: Queue[Fruit] = new Queue[apple](List(new apple), List())
//> q1 : Test.Queue[Test.Fruit] = Test$Queue@30c7da1e
q1.append(new Fruit)
//> res0: Test.Queue[Test.Fruit] = Test$Queue@506e6d5e
q1.append(new oranges)
//> res1: Test.Queue[Test.Fruit] = Test$Queue@96532d6
q1.append(new diffAppale) // i want to restrict this
//> res2: Test.Queue[Object] = Test$Queue@3796751b
关于这个问题: append函数将获取T的超类型的所有对象 这是您的原始代码已经完成的工作。请注意,
Any
是所有类型的超级类型。由于参数处于协变位置,因此对于预期类型为Any
的参数,始终可以传递子类型为Any
的值。这就是生活:)Scala感觉与Java不同,因为它是围绕声明站点差异构建的,而不是使用站点差异(可以说是比Java的泛型更好的决定)
如果需要进一步的约束,可以请求证据参数,例如
class Queue[A](leading: List[A], trailing: List[A]) {
def append(x: A) = new Queue[A](leading, x :: trailing) // ...
}
class Fruit
class Orange extends Fruit
class Apple extends Fruit
class NotFruit
val q1: Queue[Fruit] = new Queue(List(new Apple), Nil)
val q2 = q1.append(new Fruit) // ok
val q3 = q2.append(new Orange) // ok
q1.append(new NotFruit) // error - found NotFruit, required Fruit
但是:这真的没有意义。为什么这对你来说是个问题?我只想通过append函数添加一些特定的对象类型,它可以由>:,控制,我想你正在尝试考虑需要的更复杂的对象类型。如果您在特定情况下所需的返回类型为
Queue[Fruit]
,它将无论如何不允许您返回Queue[Any]
。大多数时候,当程序正确地进行类型检查时,人为地强制附加类型约束是没有意义的。无论如何,正如我在回答中所建议的,如果你真的想这样做,只需删除方差。现在我有点困惑:),你已经删除了A(+A)的覆盖率,但是你仍然可以将队列[苹果]添加到队列[水果]中,如下所示val q1:Queue[水果]=新队列(列表(新苹果),Nil)但是如果coverience被删除,我不能添加如下内容:Queue[Fruit]=new Queue[apple](List(new apple),List()),有什么区别@Sharathcandra Scala(与Java类似)是一种具有子类型的语言。A
类型的参数总是可以通过传递B类型的值来满足,因为现在AQueue[Apple]
不再是Queue[four]
的子类型,所以您不能在没有方差注释的情况下写入valq1:Queue[four]=new Queue[Apple](List(new Apple),Nil)
。您可以构造一个val q1:Queue[Fruit]=new Queue[Fruit](List(new Apple),Nil)
,因为List[+a]
在其元素类型中是协变的,因此,根据经验法则,如果类型参数的使用允许,可以使用方差注释。Scala是一种具有子类型和支持不可变数据类型的语言,使用方差注释使其使用更加顺畅。不要担心返回类型可能会被“加宽”,例如到队列[Any]
,因为在下一步中,您将看到您可能不会使用这种类型做任何事情。
def append[B >: A](x: B)(implicit ev: B <:< Seedless): Queue[B]
def append[B >: A <: Fruit](x: B): Queue[B]