Вопрос

В чем разница между

[A <: B]

а также

[+B]

в Скале?

Это было полезно?

Решение

Q[A <: B] означает этот класс Q может взять любой класс A это подкласс B.

Q[+B] Значит это Q может взять Любые класс, но если A это подкласс B, тогда Q[A] считается подклассом Q[B].

Q[+A <: B] означает этот класс Q может взять только подклассы B а также распространять отношения подкласса.

Первый полезен, когда вы хотите сделать что -то общее, но вам нужно полагаться на определенный набор методов в B. Анкет Например, если у вас есть Output класс с toFile Метод, вы можете использовать этот метод в любом классе, который можно было бы перенести Q.

Второй полезен, когда вы хотите сделать коллекции, которые ведут себя так же, как и исходные классы. Если вы возьмете B и вы делаете подкласс A, тогда вы можете пройти A в любом месте, где B ожидается. Но если вы возьмете коллекция из B, Q[B], правда ли, что вы всегда можете пройти Q[A] вместо? В общем, нет; Есть случаи, когда это было бы неправильно. Но вы можете сказать, что это правильно, используя +B (ковариация; Q ковари-следовать вместе с ...BСоблаги на подклассах).

Другие советы

Я хотел бы продлить Отличный ответ Рекса Керра С еще некоторыми примерами: допустим, у нас есть четыре класса:

 class Animal {}
 class Dog extends Animal {}

 class Car {}
 class SportsCar extends Car {}

Начнем с дисперсии:

 case class List[+B](elements: B*) {} // simplification; covariance like in original List

 val animals: List[Animal] = List( new Dog(), new Animal() )
 val cars: List[Car] = List ( new Car(), new SportsCar() )

Как вы видете Список не заботится о том, содержит ли он животных или автомобили. Анкет Разработчики списка не обеспечили соблюдение того, что, например, только автомобили могут войти в списки.

Кроме того:

case class Shelter(animals: List[Animal]) {}

val animalShelter: Shelter = Shelter( List(new Animal()): List[Animal] )
val dogShelter: Shelter = Shelter( List(new Dog()): List[Dog] )

Если функция ожидает List[Animal] параметр вы также можете пройти List[Dog] как аргумент в пользу функции. List[Dog] считается подклассом List[Animal] Из -за ковариации списка. Это не сработает, если список был инвариантным.

Теперь на границы типа:

case class Barn[A <: Animal](animals: A*) {}

val animalBarn: Barn[Animal] = Barn( new Dog(), new Animal() )
val carBarn = Barn( new SportsCar() )
/* 
error: inferred type arguments [SportsCar] do not conform to method apply's type parameter bounds [A <: Animal]
    val carBarn = Barn(new SportsCar())
                 ^
*/

Как вы видете Сарай - это коллекция, предназначенная только для животных. Анкет Здесь не разрешено автомобили.

Для моего понимания:


Первый - это граница типа параметров, в нашем случае верхний и нижний тип


Второе - это аннотация дисперсии для определения класса, в нашем случае ковариационная подклассирование B


Скала: + Java:? расширяет ковариантную подклассию

Скала: - Ява:? Super T Contravariant Подкласс

Я нашел этот пост в блоге, исследуя этот вопрос. Дает еще более глубокое объяснение дисперсии Scala, включая ее теоретическую основу в теории категории

http://blogs.atlassian.com/2013/01/covariance-and-contravariance-in-scala/

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top