2016-10-14 9 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 [? super T] (x: U) // здесь функция append будет принимать все объекты, которые являются супертипами T, Как я могу достичь аналогичного в scala (реализовать супер и расширить для дженериков, таких как java)

+0

Почему эта проблема для вас? –

+0

Я хочу добавить некоторые конкретные типы объектов только через функцию append, которая может управляться с помощью:: <: .. Это допустимо? –

+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 

Что касается вопроса:

функция Append будет принимать все объекты, которые супертип T

Это то, что уже делает ваш первоначальный код. Обратите внимание, что Any является супертипом всех типов. Поскольку аргумент находится в ковариантной позиции, всегда можно передать значение с подтипом Anyдля аргумента ожидаемого типаAny. Это жизнь :) Scala просто чувствует себя иначе, чем Java, потому что она построена вокруг отклонения от сайта и не использует дисперсию сайта (возможно, лучшее решение, чем дженерики Java).

Если вы хотите дополнительные ограничения, вы можете попросить параметра доказательства, такие как

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

Или поместить верхнюю границу (это не может быть такой же, как A из-за дисперсии A «s):

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

Но: это действительно не имеет смысла ИМХО.

+0

Теперь я немного смущен :), вы удалили оболочку A (+ A), но вы можете добавить Queue [apples] в Queue [Fruit], как показано ниже –

+0

val q1: Queue [Fruit] = new Queue (List (новый Apple), Nil) Но я не мог добавить, как показано ниже, если закрытие оболочки удалено. val q1: Queue [Fruit] = new Queue [apple] (List (новое яблоко), List()). В чем разница !!! –

+0

@sharathchandra Scala (например, Java) - это язык с субтипированием. Параметр типа 'A' ​​всегда может быть удовлетворен передачей значения типа' B <: A'. Для этого вам не нужны аннотации на отклонения, это так «встроенная» функция. Поэтому, если у вас есть 'Queue [A]' с методом 'append (x: A)', вы всегда можете вызвать этот метод со значением 'y: B', если' B <: A'. Это звучит по определению, потому что этот метод видит 'y' как значение типа' A' и может спокойно относиться к нему так, потому что 'B' имеет каждую функцию (член), которую имеет' A'. –

Смежные вопросы