简体   繁体   中英

How to implement an overriden method with a different return type?

Consider the situation where I have an abstract class in Java;

public abstract class Foo
{
    public abstract int myOperation();
}

Now, some of its subclasses may override myOperation like this;

class A extends Foo
{
    public int myOperation()
    {
            // Do stuff
    }
}

But if one subclass instead wants to return some other data type like;

class A extends Foo
{
    public Object myOperation()
    {
        // Do stuff
    }
}

I want the method name to be the same, to keep the design intact so that the clients don't necessarily select which method to call. Is there a workaround for this other than having separate methods with one being an empty implementation or using Object as the return type? Or is this a seriously bad example of OO design?

I've heard about Covariant return types in C++ and wondering whether Java has some other mechanism for this.

I'm also free to use an interface here.

You can't. Neither using inheritance, nor using an interface for this. It's going to be a compiler error so you won't be able to run your program at all.

You could return java.lang.Object and return whatever object you want. In case you need to return a primitive, you could return its object wrapper.

"is this a seriously bad example of OO design" Yep. You can't do it.

Java has co-variant return types but the return type must be more specific, not less specific. If a method in a parent class return int then all its sub-type must do as well otherwise the caller of such a method doesn't really know what type it is getting.

Foo foo = new A()
int i = foo.method();

If method() returns anything but int this statement no longer makes sense.

When you can do is if the method in the super class return Object and a dervice class return Number then the sub-class of both can return Integer

You can have different data types, when you use return type as derived ie,Co-varients. when you use primitive data type, you cannot change it.

If Super class method is any derived data type, while over ridding in the sub-class return type can be same derived data type or sub-class derived data type.

This is not possible, because the method, declared in the abstract class, defines a contract: it returns an int. This contract must be respected by all implementations. What would happen if you did:

Foo foo = new A();
int i = foo.myOperation();

It would break, because myOperation would not return an int . That's why it's not allowed.

What is allowed, though, is the following:

public abstract class Foo {
    public abstract Object myOperation();
}

public class A extends Foo {
    @Override
    public String myOperation() {
        return "some string";
    }
}

In this case, the contract is respected. The method must return an Object, it returns a String, and a String is an Object.

You cannot do this, because it would break the contract of Foo .

A a = new A();
someUtilityMethod(a);

...

void someUtilityMethod(Foo foo){
   int i = foo.myOperation();    // This would break
}

This principle is called Liskov substitution principle and it is the foundation upon which OO is built.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM