Nicofisi Nicofisi - 4 years ago 121
Scala Question

An issue with generics types in method parameters

can someone explain why the code below doesn't work?

scala> abstract class A[T] {}
defined class A

scala> class B {}
defined class B

scala> object C extends A[B] {}
defined object C

scala> def method(arg: A[Any]): Unit = {}
method: (arg: A[Any])Unit

scala> method(C)
<console>:14: error: type mismatch;
found : C.type
required: A[Any]
Note: B <: Any (and C.type <: A[B]), but class A is invariant in type T.
You may wish to define T as +T instead. (SLS 4.5)
method(C)


I have an abstract class, here named
A
, and I'd like to be able to pass anything that extends A[AnythingHere] as an argument to the method
method
. In Java I would write
public void method(A<?> arg) {}
, but I don't know how to make it work with Scala, as there is no
?
.

I also tried adding that
+
to the
+T
, but after testing and searching for what it does, I didn't find it helpful here. Just the warning disappeared

Thanks in advance

Answer Source

The code does not work because if you want to use generics in variant or contravariant in Scala, you have to declare it explicitly. Otherwise, the Java invariant behaviour is implemented.

Java is by default invariant. This means that if A < B, thenList[A] and List[B] do not have any hierachical relationship between them.

Scala lets you to use declare generic type as covariant or contravariant, which means

  1. If you declare a generic as covariant, then if if A < B, thenList[A] < List[B]. To do this, you have to declare the generic using the syntax class A[+T]
  2. If you declare a generic as contravariant, then if if A < B, thenList[A] > List[B]. To do this, you have to declare the generic using the syntax class A[-T]
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download