In my application I want to use such a trait:
trait HasBuffer[+A] {
var items = Buffer[A]()
def add[A](item: A) { items += item }
def remove[A](item: A) { items -= item }
def set(is: Buffer[A]) { items = is }
def clear { items clear }
}
Classes that inherit this trait should be able to buffer any instances of classes who are children of the class A. However on both the add and remove methods the compiler complains about the item being added or removed from the items that “type mismatch; found : item.type (with underlying type A) required: A”. How should I understand this? What is my mistake here and what to do?
You are parameterizing the methods with another type parameter
Athat differs from the one of your class definition. Here’s the version you wrote with renamed parameters:Now it should be clear, why the compiler rejects this.
Instead you can simply write the methods like this:
However, then you will still receive compiler errors stating that covariant type
Aoccurs in contra- and invariant positions.The point of being covariant is that if you expect a
HasBuffer[AnyVal]one may pass in aHasBuffer[Int]. However, if you expectAnyValand use that type for theaddmethod as well, you would be able to add a completely different type to yourHasBuffer[Int]. Hence, the compiler rejects this.Instead, you will have to provide a lower bound on the type parameter like this:
With this you may now have methods like the following:
This method will work on all sorts of
HasBuffertype parameter combinations that satisfy the required lower bound.Mentally compare this with the idea of not providing a lower bound. Then the method would have become something like this:
If you call this with an object of type
HasBuffer[Int]and aDoubleit’ll be all happy. You probably won’t be happy lateron though, when you find your buffer that should contain onlyInts now contains aDouble.