简体   繁体   English

如何忽略/绕过重写的方法?

[英]How to ignore/bypass an overridden method?

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.我对 Java 还很陌生,想知道如何完成以下任务,以及它是否被认为是糟糕的风格,即使它是可能的。 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?但是我现在可以使用相同的“ f.swim() ”语法调用 Fish 的f.swim()吗?

// 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."关于 SO 用户 Rinke 在下面的回答——他说“你可以将你的金枪鱼实例分配给金枪鱼和鱼类型的变量,但它永远是金枪鱼。”

The last part of that sentence got my novice OOD brain wondering - why allow a "super object" to refer to a "sub object" anyway?这句话的最后一部分让我的新手 OOD 大脑想知道 - 为什么允许“超级对象”引用“子对象”? 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?允许 Fish 对象能够“在”指代鱼或金枪鱼时“切换”有什么好处? Thank you.谢谢。

Edit 2:编辑2:

Here is some example code to illustrate the concept of SO user Rinke's "answer to edit" response, below.下面是一些示例代码,用于说明 SO 用户 Rinke 的“编辑答案”响应的概念,如下所示。

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();
}

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 (ie 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().请注意,您可以通过调用 super.swim() 从子类内部调用超类的 Swim 方法。

Of course, if you don't override the swim method then tunas simply inherit the method from fish.当然,如果您不覆盖游泳方法,那么金枪鱼只需从fish 继承该方法。 In that case the fish-code will be run on the tuna instance.在这种情况下,fish-code 将在 tuna 实例上运行。

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.也许您需要将金枪鱼提供给接受鱼的其他人的 API。

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.所以你得到了void eat(Fish f) ,大自然(由你控制之外的一段代码实现)为你的熊提供鱼。

To leave the funny fish example: look at Collections.sort() .离开有趣的鱼的例子:看看Collections.sort() You can sort any list.您可以对任何列表进行排序。 It doesn't matter if it's an ArrayList or a LinkedList.它是 ArrayList 还是 LinkedList 都没有关系。

You cannot bypass Tuna.java 's swim() method if it's overridden.如果Tuna.java swim()方法被覆盖,则无法绕过它。 But what you can do is, in overridden swim() , inside Tuna.java , you can make a call to super class' method.但是您可以做的是,在覆盖的Tuna.java swim() ,在Tuna.java ,您可以调用超类的方法。

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.另一种选择是,以这种方式更改Tuna.java中的Tuna.java swim()方法的签名,使其成为Fish.java swim()的重载版本,而不是被覆盖的版本。

can I now get Fish's swim() method to be invoked, using the same "f.swim()" syntax?我现在可以使用相同的“f.swim()”语法调用 Fish 的 Swim() 方法吗?

No, you can't.不,你不能。

Although it is not possible.虽然这是不可能的。 I am using @Deprecated to indicate that the specific method is unused.我正在使用 @Deprecated 来指示未使用特定方法。

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我将接口定义为 Swimable

public interface Swimmable {
    public void swim();
}

Then I make Fish implement this interface然后我让 Fish 实现这个接口

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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