2016-10-14 50 views
2
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] = [email protected] 

q1.append(new Fruit)        
//> res0: Test.Queue[Test.Fruit] = [email protected] 

q1.append(new oranges)       
//> res1: Test.Queue[Test.Fruit] = [email protected] 

q1.append(new diffAppale) // i want to restrict this    
//> res2: Test.Queue[Object] = [email protected] 

在这里,我可以添加附加功能,什么都反对,我可以,我可以看到生成的类型被降级为最小公分母斯卡拉上限和下限

但我想有相同的行为作为Java,说def append [?超级T](X:U)//此处附加功能将它们是T形的超类型的所有对象,我怎么能实现类似一个在斯卡拉(实现超和扩展对于像Java泛型)

+0

为什么这是你的问题吗? –

+0

我想添加一些特定的对象类型只能通过追加功能,这可以通过>:,<:..控制它是否易于? –

+0

我认为你正试图想要更复杂的需要。如果您在特定情况下需要的返回类型是Queue [Fruit],它总是不允许您返回Queue [Any]。大多数情况下,当程序正确地进行类型检查时,人为地强制实施其他类型限制是没有意义的。无论如何,正如我在答案中所建议的那样,如果你真的想要这样做,只需删除差异。 –

回答

1

我不明白为什么你想限制这个,或者为什么返回一个更通用的新的不可变对象会给你带来问题。

但是,如果你不想说方差,只要删除所有方差注释:

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 

至于问题:

附加功能将它们的所有对象的T超

这是你原来的代码已经这样做了。请注意,Any是所有类型的超类型。由于参数是在协变位置时,它总是可以通过与子类型的Any一个值预期类型Any的参数。这就是生活:) Scala感觉与Java不同,因为它是围绕声明网站差异而建立的,并且不使用网站差异(可以说是比Java的泛型更好的决定)。

如果您想进一步的限制,你可以要求一个证据参数如

def append[B >: A](x: B)(implicit ev: B <:< Seedless): Queue[B] 

或者换一个上限(这不可能是一样A因为A的方差):

def append[B >: A <: Fruit](x: B): Queue[B] 

但是:真的没有意义恕我直言。

+0

现在我有点糊涂了:),你已经删除A的coverience(+ A),但你仍然可以添加队列[苹果]到队列[水果]如下 –

+0

VAL Q1:队列[水果] =新的队列(名单(新苹果),无)但是我不能像下面添加如果覆盖被删除val q1:队列[水果] =新队列[苹果](列表(新苹果),列表()),有什么区别! –

+0

@sharathchandra Scala(如Java)是一种具有子类型的语言。通过传递类型'B <:A'的值可以始终满足'A'类型的参数。你不需要差异注释,这是一个“内置”功能。所以如果你有一个带有方法append(x:A)的'Queue [A]',如果'B <:A',你总是可以用'y:B'来调用这个方法。根据定义,这听起来很合理,因为该方法将'y'看作类型'A'的值,并且可以安全地对待它,因为'B'具有'A'所具有的每个特征(成员)。 –