0
votes

I cannot figure out how to specify the return type of a method an abstract class A, if the same method of the concrete classes have different return (sub)types:

abstract class A {
    def method: List[Common (?)]   // I want to force all subclasses to define this method
}

class B1 extends A {
    def method(a,b,c): List[Sub1] = {...}
}

class B2 extends A {
    def method(a,b,c): List[Sub2] = {...}
}

I tried to define a common trait of Sub1 and Sub2:

abstract class Common   // or abstract class
case class Sub1 extends Common
case class Sub2 extends Common

but I keep getting this:

Compilation error[class B1 needs to be abstract, 
since method "method" in class A of type => List[Common] is not defined]

If I don't define the return type in class A, I get the same error with ... type => Unit ... instead.

How can I solve that?

2
I see no Java in this question.Marko Topolnik
Ok I removed the tag. I thought it was an abstract question about inheritance.JulienD
No, it's quite specific to Scala's type system.Marko Topolnik
@MarkoTopolnik No, it isn't. It's an inheritance problem.Michael Zajac
@m-z It's either a fully abstract problem about general inheritance, or it is a specific problem about one language's type system. It is definitely not a problem specific to Scala and Java.Marko Topolnik

2 Answers

5
votes
 def method: List[Common]

Is not the same as

 // returns `List[Common]` to simplify things, but it would be the same if we returned a sub-type
 def method(a: ?, b: ?, c: ?): List[Common] = {...}

The first is a parameterless method that returns a List[Common], and the second is a method with three parameters that returns a List[Common]. The compiler sees these as two completely different methods. The fact that they have the same name means nothing.

The compiler is complaining because def method: List[Common] is not defined in the subclasses of A.

1
votes

This compiles:

  abstract class Common   // or abstract class
  case class Sub1() extends Common
  case class Sub2() extends Common

  abstract class A {
    def method(): List[Common]
  }

  class B1 extends A {
    def method(): List[Sub1] = ???
  }

  class B2 extends A {
    def method(): List[Sub2] = ???
  }

All I have done is:

  • add the () to Sub1() and Sub2()
  • return List[Common] from A

EDIT

As @m-z mentioned, it works because every def method() has the same signature now.