2017-09-03 72 views
3

考虑下面的两个代码。他们完成相同的目标:只有这样A[T] -s可以存储在T延伸C斯卡拉存在与协方差

但是他们使用两种不同的方法来实现这一目标的Container

1)existentials

2)协方差

我更喜欢第一种解决方案,因为A保持简单。为什么我会想要使用第二种解决方案(协方差),有什么理由吗?

我与第二个解决方案的问题是,它是在这个意义上,它不应该是A -s责任来形容我可以在一个容器仓库并没有什么不自然,这应该是容器的责任。第二种解决方案也是更复杂一旦我想开始在A上运行,然后我必须处理所有与协变有关的东西。

使用第二种(更复杂,不太自然)的解决方案会带来什么好处?

object Existentials extends App { 

    class A[T](var t:T) 

    class C 

    class C1 extends C 

    class C2 extends C 

    class Z 

    class Container[T]{ 
    var t:T = _ 
    } 

    val c=new Container[A[_<:C]]() 
    c.t=new A(new C) 
    // c.t=new Z // not compile 

    val r: A[_ <: C] = c.t 

    println(r) 
} 

object Cov extends App{ 
    class A[+T](val t:T) 

    class C 

    class C1 extends C 

    class C2 extends C 

    class Z 

    class Container[T]{ 
    var t:T = _ 
    } 

    val c: Container[A[C]] =new Container[A[C]]() 
    c.t=new A(new C) 
    //c.t=new A(new Z) // not compile 

    val r: A[C] = c.t 

    println(r) 
} 

EDIT(响应阿列克谢的答案):

评论: “我与第二个解决方案的问题是,它不是在某种意义上说,它不应该是作为责任自然描述我可以在集装箱中储存什么,哪些不是,这应该是集装箱的责任。“

如果非要class A[T](var t:T)这意味着,我可以仅存储A[T]在容器-s和不(A[S]其中S<:T),在任何容器。

但是,如果我有class A[+T](var t:T)那么我可以存储A[S]哪里S<:T以及任何容器。

因此,当声明A或者是不变的或协变时,我决定哪种类型的A [S]可以存储在一个容器中(如上所示),这个决定发生在声明A

不过,我认为,这个决定应该发生,相反,在容器的声明,因为它是具体的东西将被允许进入该容器中,只有A[T] -s或也A[S]其中S<:T -s容器。

换句话说,改变A[T]方差具有全球影响,同时改变一个容器的类型参数从A[T]A[_<:S]已经容器本身上的良好限定的局部作用。所以“变化应该有局部效应”的原则也有利于生存解决方案。

回答

4

在第一种情况下,A更简单,但在第二种情况下它的客户是。由于通常有多个地方使用A,这通常是值得的折衷。你自己的代码演示了它:当你需要在第一种情况下(在两个地方)写A[_ <: C]时,你可以在第二种情况下使用A[C]

此外,在第一种情况下,你可以只是A[C]其中A[_ <: C]是真正需要的。比方说,你有一个方法

def foo(x: A[C]): C = x.t 

现在你不能叫foo(y)y: A[C1]即使它将使意义:y.t确实有型C

当这种情况发生在您的代码中时,它可以被修复,但第三方呢?

当然,这适用于标准库的类型以及:如果类型,如MaybeList不协变,无论是对所有签名方法服用/返回他们将不得不更加复杂或许多程序这是目前有效并做出完美的感觉会打破。

它不应该是我的责任来描述我可以在一个容器中存储什么,什么不是,这应该是容器的责任。

差异不是关于什么,你可以存储在一个容器;它是关于何时A[B]A[C]的子类型。这个说法有点像说你不应该有extends:否则class Apple extends Fruit允许你存储AppleContainer[Fruit],并决定是Container的责任。

+0

感谢您的回答。 “另外,如果你忘记在一种方法中使用正确的存在,任何其他调用它的地方都不能使用存在类型(没有不安全的未经检查的转换)。”你能举一个简单的例子吗?我不完全明白你的意思。 – jhegedus

+0

“在第一种情况下,A更简单,但在第二种情况下,其客户是这样。”客户如何更简单?我不明白,你能举个例子吗? – jhegedus

+0

@jhegedus查看编辑。 –