sjb
sjb

Reputation: 55

underscore "class needs to be abstract since method is not defined" error

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

Answers (2)

Luigi Plinge
Luigi Plinge

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

Dave Cahill
Dave Cahill

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

Related Questions