Jakub Nowacki Jakub Nowacki - 22 days ago 6
Scala Question

Overriding abstract method of Java class in Scala with bounded inheritence

I have an abstract class in a library I wanted to implement in Scala, which has abstract copy method with bounded inheritance as follows:

// Java code
public abstract class Base {
public abstract <T extends Base> T copy();
}


When I create a class in Java it works fine, i.e.

public class FromBase extends Base {
@Override
@SuppressWarnings("unchecked")
public FromBase copy();
}


But if I try to do it in Scala the below gives
method 'copy' overrides nothing
:

class FromBase extends Base {
override def copy(): FromBase = new FromBase()
}


And the below IDE-suggested works but requires call with type
v.copy[FromBase]()
to work:

class FromBase extends Base {
override def copy[T <: Tuple](): T = (new FromBase).asInstanceOf[T]
}


Since the method can be called from Java, I need a copy without generic to work, as in the Java example.

Answer

The declaration of Base.copy says it can return whatever subtype of Base it's asked for. It's entirely valid to write

Base base = new FromBase;
AnotherBaseSubclass base2 = base.copy();
// same as AnotherBaseSubclass base2 = base.<AnotherBaseSubclass>copy();

This obviously can't work if FromBase.copy actual return type is FromBase. So the "warning" you are suppressing should be an error and Scala doesn't allow it.

It's likely that you actually need T on Base, not copy. If you fix this:

// Java code
public abstract class Base<T extends Base> {
      public abstract T copy();
}

// Scala
class FromBase extends Base[FromBase] {
    override def copy() = new FromBase
}

it will compile and not require any casts or suppressed warnings.