Reputation: 55
With scala 2.10.2, I have a code that extends
from class scala.swing.ListView[SomeClass]
and I get this error:
src/some.scala:100: error: class Some_Renderer needs to be abstract, since method componentFor in class Renderer of type (list: scala.swing.ListView[_ <: SomeClass], isSelected: Boolean, focused: Boolean, a: SomeClass, index: Int)scala.swing.Component is not defined
private class Some_Renderer extends ListView.Renderer[SomeClass]
EDIT: "an extra Note" is actually the error here, as commented B[String]
must be B[_]
.
EDIT: some real example follows
I have reproduced it as the following example, though with an extra Note:
scala> class B[A] { val m : Int = 0 }
defined class B
scala> abstract class C[A] { def f(l: B[_]):Int }
defined class C
scala> private class D extends C[String] { def f(l: B[String]):Int = { l.m } }
<console>:9: error: class D needs to be abstract, since method f in class C of type (l: B[_])Int is not defined
(Note that B[_] does not match B[String]: their type parameters differ)
private class D extends C[String] { def f(l: B[String]):Int = { l.m } }
EDIT: MWE
import scala.swing.{Component, Label, ListView}
class Test
object Retn extends Label { opaque = false }
private class TestRenderer extends ListView.Renderer[Test]
{
def componentFor(list: ListView[_], isSelected: Boolean, focused: Boolean, test: Test, index: Int): Component =
{
val retn = Retn
retn
}
}
<console>:9: error: class TestRenderer needs to be abstract, since method componentFor in class Renderer of type (list: scala.swing.ListView[_ <: Test], isSelected: Boolean, focused: Boolean, a: Test, index: Int)scala.swing.Component is not defined
private class TestRenderer extends ListView.Renderer[Test]
^
EDIT: MWE
I am only trying to patch that line of code, and do scala
programming by no means.
Yet I do not understand what is the problem with this example. I found similar questions
but not with this underscore ("_
") thing.
The example tries to provide an implementation for the abstract method f
from class C[A]
.
Thank s for your comments or answers about this issue.
Upvotes: 2
Views: 1943
Reputation: 51109
B[_]
is an "existential type", but you can understand this as being roughly equivalent to B[Any]
.
The error message tells you Note that B[_] does not match B[String]: their type parameters differ
. You wouldn't expect to be able to replace a List[Any]
parameter with a List[String]
in an overridden definition, would you? Because then what happens when you pass it a List[Int]
, which is also a bona fide List[Any]
as required in the abstract class?
Solution: replace def f(l: B[String]):Int = ...
with def f(l: B[_]):Int = ...
Edit: the problem with your MWE is that you've defined the TestRenderer
class on one line, then you've written a code block delimited by {
}
on the next... this will be interpreted as you intend in normal code (although it's better to put the {
at the end of the previous line) but since you're in the REPL the class definition is interpreted as soon as you hit return. Solution: either put the {
at the end of the private class ...
line or type in :paste
to allow you to write the lot before it's interpreted.
... at least, I assume that's what your problem is. The MWE works fine for me in scala 2.10.0 REPL, although I get a slightly different error message if I just type in the private class ...
line.
Upvotes: 2
Reputation: 448
I'm not sure what the constraints are in your original case, but in your example, could you use B[_] instead of B[String] when you override f?
class D extends C[String] { def f(l: B[_]):Int = { l.m } }
The underscore in this case is an existential type, and can can be any subtype of Any. See here for more information on existential types in Scala.
Upvotes: 1