3

I tried to compile and run the following Scala source code:

class People(val name: String)
class Student(studentName: String) extends People(studentName)

def getNames(array: Array[People]) = { array.map(_.name) }

getNames(Array[Student](new Student("Mike"), new Student("Tom")))

I got error message:

Name: Compile Error
Message: <console>:30: error: type mismatch;
 found   : Array[Student]
 required: Array[People]
Note: Student <: People, but class Array is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: People`. (SLS 3.2.10)
       getNames(Array[Student](new Student("Mike"), new Student("Tom")))

It's as expected because Array[Student] is not a subtype of Array[People].

Then I updated

getNames(Array[Student](new Student("Mike"), new Student("Tom")))

to

getNames(Array(new Student("Mike"), new Student("Tom")))

The error was gone. So I'm wondering in Scala what is the difference between Array and Array[Type], especially when it's passed as a method parameter.

Thanks in advance!

ihainan
  • 65
  • 7

1 Answers1

1

This is because Scala arrays don't repeat the covariance mistake of Java. In Java you can do:

Student[] students = new Student[10];
Person[] people = students; // ok in Java arrays are covariant
people[1] = new Person(); // RuntimeException in Java!!

Scala is safer than that (like Java generic collections).

You should always use the specific version of collections in order to get better type safety. Your Array example detects the generic parameter from the function call - which is Array[Student].

Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • Thanks much for your answer, it does help! – ihainan Aug 19 '17 at 09:40
  • I'm sorry, but the second part of this answer is wrong. You're not getting a "non-generic" array, you're getting an `Array[People]`, because the expected type of the expression is supplied by the `getNames` method. – Joe Pallas Aug 20 '17 at 01:12