Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between A<:B and +B in Scala?

Tags:

scala

variance

What's the difference between

[A <: B] 

and

[+B] 

in Scala?

like image 739
jsadfeew Avatar asked Dec 25 '10 19:12

jsadfeew


People also ask

What does <: mean in Scala?

It means an abstract type member is defined (inside some context, e.g. a trait or class), so that concrete implementations of that context must define that type. However, there is a constraint that this type ( Currency ) must actually be a subtype of AbstractCurrency .

What are the differences between any AnyRef and AnyVal?

Any has two direct subclasses: AnyVal and AnyRef. AnyVal represents value types. There are nine predefined value types and they are non-nullable: Double, Float, Long, Int, Short, Byte, Char, Unit, and Boolean. AnyRef represents reference types.

What is difference between object and class in Scala?

Difference Between Scala Classes and Objects Definition: A class is defined with the class keyword while an object is defined using the object keyword. Also, whereas a class can take parameters, an object can't take any parameter. Instantiation: To instantiate a regular class, we use the new keyword.

What does => int mean in Scala?

It means when you call the method, the argument is not evaluated before the method is executed, but rather, it is evaluated each time it is referred to inside the method.


2 Answers

Q[A <: B] means that class Q can take any class A that is a subclass of B.

Q[+B] means that Q can take any class, but if A is a subclass of B, then Q[A] is considered to be a subclass of Q[B].

Q[+A <: B] means that class Q can only take subclasses of B as well as propagating the subclass relationship.

The first is useful when you want to do something generic, but you need to rely upon a certain set of methods in B. For example, if you have an Output class with a toFile method, you could use that method in any class that could be passed into Q.

The second is useful when you want to make collections that behave the same way as the original classes. If you take B and you make a subclass A, then you can pass A in anywhere where B is expected. But if you take a collection of B, Q[B], is it true that you can always pass in Q[A] instead? In general, no; there are cases when this would be the wrong thing to do. But you can say that this is the right thing to do by using +B (covariance; Q covaries--follows along with--B's subclasses' inheritance relationship).

like image 97
Rex Kerr Avatar answered Oct 13 '22 17:10

Rex Kerr


I would like to extend Rex Kerr's excellent answer with some more examples: Let's say we have four classes:

 class Animal {}  class Dog extends Animal {}   class Car {}  class SportsCar extends Car {} 

Let's start with variance:

 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() ) 

As you can see List does not care whether it contains Animals or Cars. The developers of List did not enforce that e.g. only Cars can go inside Lists.

Additionally:

case class Shelter(animals: List[Animal]) {}  val animalShelter: Shelter = Shelter( List(new Animal()): List[Animal] ) val dogShelter: Shelter = Shelter( List(new Dog()): List[Dog] ) 

If a function expects a List[Animal] parameter you can also pass a List[Dog] as an argument to the function instead. List[Dog] is considered a subclass of List[Animal] due to the covariance of List. It would not work if List was invariant.

Now onto type bounds:

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())                  ^ */ 

As you can see Barn is a collection only intended for Animals. No cars allowed in here.

like image 29
mucaho Avatar answered Oct 13 '22 18:10

mucaho