Master Bob
Master Bob

Reputation: 63

Implementing abstract methods in a subclass in Java

I've made my code as generic as possible to try and help people in the future. My abstract class has a method of the type class and and an input of the type class. In the class that extends the abstract, I try to implement that method to no avail. What am I doing wrong?

public abstract class A {
    public abstract A method1(A arg);
}

public class B extends A {
    @Override
    public B method1(B arg) { "...insert code here"} // Error: The method method1(B) must override or implement a supertype method
}

Upvotes: 5

Views: 3723

Answers (5)

Andy Turner
Andy Turner

Reputation: 140544

Think about the Liskov substitution principle: in order to be indistinguishable from a superclass, the subclass must accept all of the same parameters that the superclass would; and return something that the superclass might.

Another way to put this is that the subclass method can:

  • Return a more specific type that the superclass method (since this is a value that the superclass might return); for example, if the superclass returns Object, the subclass can return a String, because all Strings are Objects.

    This is called a covariant return type, and is permitted in Java. Subclasses can not only return more specific return types, they can also throw more specific checked exceptions than the superclass; but they can also not declare that they throw the checked exceptions thrown by the superclass method.

  • Accept a more general type than the superclass method (since this allows the subclass to accept all parameters that the superclass would).

    This would be called a contravariant parameter type; but it is not permitted in Java. The reason is to do with the way that overloads are selected in Java: unfortunately, the method signatures (which includes the parameter types, but not the return type) have to be identical.

The relevant section of the language spec is JLS Sec 8.4.8.3.

Your problem is making the parameter type B: this is more specific than A, so an instance of B is not substitutable for an instance of A, because A.method1 accepts a parameter A, whereas B.method1 does not.

Make B.method1 take a parameter of type A.

Upvotes: 3

davidxxx
davidxxx

Reputation: 131526

To achieve what you want : associating the type of the argument to the declared class, you could use generics.

abstract class :

public abstract class A <T extends A<T>> {
    public abstract T method1(T arg);
}

concrete class :

public class B extends A<B> {
    @Override
    public B method1(B arg) { 
     ...
      return ...
    }
}

Upvotes: 3

Ritesh Singh
Ritesh Singh

Reputation: 93

Every thing you have written is right except overidden method argument type,you can't change the signature of superclass abstract method while overiding in subclass.

public abstract class A {
    public abstract A method1(A arg);
}

public class B extends A {
    @Override
    public B method1(A arg) { "...insert code here"} // Error: The method method1(B) must override or implement a supertype method
}

Upvotes: 1

BeginnersSake
BeginnersSake

Reputation: 680

The type and no of parameter should remain. The return type, if it is of primitive type, should remain same, but if it is of reference type then it can be of subclass type.

In your case change this public B method1(B arg) { "...insert code here"} to public B method1(A arg) { "...insert code here"}

Upvotes: 2

Joe C
Joe C

Reputation: 15714

The contract of A.method1 means that every object that is an A must have a method1 which can take any A object.

In the case of B.method1, it can take a B object, but it cannot take another A.

Upvotes: 0

Related Questions