Reputation: 635
Scala 2.12 here. I have the following classes:
abstract class AbstractCollector {
def name() : String
def collect() : Map[String,AnyVal]
}
class NativeSystemCollector(sysInfo : SystemInfo) extends AbstractCollector {
override def name(): String = "NativeSystem"
override def collect(): Map[String, AnyVal] = ???
}
Now I'm trying to write a "provider" method that returns a List[AbstractCollectors]
:
def nativeSystemCollector() : NativeSystemCollector = new NativeSystemCollector(systemInfo())
def collectors() : List[AbstractCollector] = {
var collectors = List[AbstractCollector]()
collectors += nativeSystemCollector()
collectors
}
This code gives me a compiler error at collectors += nativeSystemCollector()
:
"Type mismatch, expected: String, actual: NativeSystemCollector"
Any ideas as to why the compiler thinks collectors
is a list of Strings when I clearly declare it as a new list of AbstractCollectors
?!?
Upvotes: 0
Views: 42
Reputation: 3464
You should use ListBuffer
over List
when dealing with mutable lists. For example:
def collectors() : List[AbstractCollector] = {
var collectorList: ListBuffer[AbstractCollector] = ListBuffer[AbstractCollector]()
collectorList += nativeSystemCollector()
collectorList.toList
}
If you really want to use a List
, use the :+
symbol:
def collectors() : List[AbstractCollector] = {
val collectorList: List[AbstractCollector] = List[AbstractCollector]()
collectorList :+ nativeSystemCollector()
}
Looking at +=
, it is constructed like this:
implicit final class any2stringadd[A](private val self: A) extends AnyVal {
def +(other: String): String = String.valueOf(self) + other
}
Since List[AbstractCollector] doesn't have a +=
method, I think it assumes you are dealing with Strings and falls over.
Read more here about adding to Lists.
Upvotes: 2
Reputation: 44992
It does not think that collectors
is a List[String]
.
Instead, it notices that collectors
is immutable and does not have +=
method. So it tries to desugar
collectors += nativeSystemCollector()
into
collectors = collectors + nativeSystemCollector()
and then doesn't know what the +
is supposed to mean. Since there is no +
method on List
, it implicitly converts collectors
into a String
, but then notices that nativeSystemCollector()
is not another String
, and gives up.
If you want to construct a list by appending elements, use a mutable ListBuffer
instead:
val collectors = collection.mutable.ListBuffer[AbstractCollector]()
collectors += nativeSystemCollector()
collectors.toList
Appending to a List
is expensive anyway.
Upvotes: 3