How to ignore/bypass an overridden method?

眉间皱痕 提交于 2020-08-25 07:31:49

问题


I'm fairly new to Java and would like to know how to accomplish the following task, and also, whether it is considered bad style, even if it is possible. Thank you.

Fish f;  // Fish is a superclass,
Tuna t = new Tuna();  // to which Tuna is a subclass.

f=t;  // the Fish object "f" now refers to the Tuna object "t".

// Both Fish and Tuna have an identical method (signature wise) called swim() ,
f.swim();  // and so Tuna's overridden swim() method is invoked here.

But can I now get Fish's swim() method to be invoked, using the same "f.swim()" syntax?

// I would now like Fish's swim() method to be invoked here,
// but is it bad style and/or am I missing some point about OOP?
f.swim();

Edit:

Re: answers, thanks people! Regarding SO user Rinke's answer below - he states that "You can assign your tuna instance to both tuna and fish typed variables, but it'll always be a tuna."

The last part of that sentence got my novice OOD brain wondering - why allow a "super object" to refer to a "sub object" anyway? What is the benefit of this flexibility? What benefit is there in allowing a Fish object the ability to "switch between" referring to either a fish or a tuna? Thank you.

Edit 2:

Here is some example code to illustrate the concept of SO user Rinke's "answer to edit" response, below.

Bear b = new Bear();
Fish f = getAnyFish();
b.eat(f);

Fish getAnyFish(){
    //To toggle the returned fish type, change true to false
    if (true) return new Tuna();
    else return new Salmon();
}

回答1:


The short answer is "No". The confusion here comes from the difference between run-time types and declared types. You can assign your tuna instance to both tuna and fish typed variables, but it'll always be a tuna. Hence, if you call the swim method on that object the tuna will swim like a tuna (i.e. the overridden method will be called).

Note that you can call the swim method of a superclass from within the subclass by invoking super.swim().

Of course, if you don't override the swim method then tunas simply inherit the method from fish. In that case the fish-code will be run on the tuna instance.

Answer to edit:

You don't always control the code you use. Maybe you need to provide your tuna to someone else's API that accepts fish.

From the opposite perspective: maybe you're implementing a bear. Bears eat fish. You don't want to care if it's a tuna or a salmon. So you get void eat(Fish f), where mother nature (implemented by a piece of code outside of your control) provides fish to your bear.

To leave the funny fish example: look at Collections.sort(). You can sort any list. It doesn't matter if it's an ArrayList or a LinkedList.




回答2:


You cannot bypass Tuna.java's swim() method if it's overridden. But what you can do is, in overridden swim(), inside Tuna.java, you can make a call to super class' method.

Tuna.java

@Override
public void swim() {
   super.swim(); // This will call Fish.java's swim() method.
   // rest of the code
}

The another option is, change the signature of swim() method in Tuna.java in such a way, that it becomes the overloaded version of Fish.java's swim(), but not the overridden.




回答3:


can I now get Fish's swim() method to be invoked, using the same "f.swim()" syntax?

No, you can't.




回答4:


You can use a different approach to this if you really want to get the swim method of the parent class. I define an interface as Swimmable

public interface Swimmable {
    public void swim();
}

Then I make Fish implement this interface

public class Fish implements Swimmable {

@Override
public void swim() {
    System.out.println("Fish");
    }
}

And my Tuna class as

public class Tuna extends Fish {
//Anything I want the Tuna to have extra 
}

Now with your same code

Fish f;
Tuna t = new Tuna();
f=t;
f.swim(); //This will call the Fish's method


来源:https://stackoverflow.com/questions/20262693/how-to-ignore-bypass-an-overridden-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!