java 将超类作为参数传递给需要子类的方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/394299/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 12:12:24  来源:igfitidea点击:

Passing superclass as parameter to method expecting sub class

javainheritancemethodspolymorphismoverloading

提问by Rocco

I have an object tree that looks something like

我有一个看起来像的对象树

           Ball
          /    \
  LegalBall    IllegalBall

And I have 2 methods:

我有两种方法:

class o {
AddBall(LegalBall l)
AddBall(IllegalBall i)
}

in another class I'd like to do the following:

在另一堂课中,我想执行以下操作:

o.AddBall(myBall);

where myBall is of type Ball. And get it to call the correct method depending on the subtype. Apparently I can't do this... the arguments are not applicable.

其中 myBall 是 Ball 类型。并让它根据子类型调用正确的方法。显然我不能这样做......这些论点不适用。

Does anyone know how I can achieve what I want? Or if there is a good work around

有谁知道我怎样才能达到我想要的?或者如果有一个很好的解决方法

Thanks

谢谢

EDIT : the application I'm trying to build is a Cricket scorecard type thing. So depending on the type of ball that is bowled various other elements should change.

编辑:我正在尝试构建的应用程序是 Cricket 记分卡类型的东西。因此,根据投出的球的类型,其他各种元素应该会发生变化。

my original intention was to be able to specify the ball type and runs scored from some form of UI and then create an appropriate type ball from a BallFactory and then for example when I send a no ball to the team score it will add the value onto the team score but also add the value to the no balls counter. But when i give the same ball to the Batsmens Analysis to deal with it should only score value-1 to the batsmens total..

我的初衷是能够指定球类型并从某种形式的用户界面得分,然后从 BallFactory 创建一个适当类型的球,然后例如当我向球队得分发送一个无球时,它会将值添加到球队得分,但也将价值添加到无球计数器中。但是当我将同一个球交给击球手分析来处理时,它应该只对击球手的总得分为 1。

I hope thats not too bad an explanation of my original intention.

我希望这对我的初衷没有太糟糕的解释。

回答by dalle

You could use the Visitor pattern.

您可以使用访问者模式

class Basket {
    void AddBall(LegalBall l) {
        System.out.println("LegalBall added to basket");
    }

    void AddBall(IllegalBall i) {
        System.out.println("IllegalBall added to basket");
    }
}

interface Ball {
    void AddBall(Basket b);
}

class LegalBall implements Ball {
    void AddBall(Basket b) {
        b.AddBall(this);
    }
}

class IllegalBall implements Ball {
    void AddBall(Basket b) {
        b.AddBall(this);
    }
}

or to make it more general:

或者让它更一般:

interface BallVisitor {
    void visit(LegalBall l);
    void visit(IllegalBall i);
}

interface Ball {
    void accept(BallVisitor v);
}

class LegalBall implements Ball {
    void accept(BallVisitor v) {
        v.visit(this);
    }
}

class IllegalBall implements Ball {
    void accept(BallVisitor v) {
        v.visit(this);
    }
}

class Basket implements BallVisitor {
    void visit(LegalBall l) {
        System.out.println("LegalBall added to basket");
    }

    void visit(IllegalBall i) {
        System.out.println("IllegalBall added to basket");
    }
}

回答by Federico A. Ramponi

You should try to implement only onemethod:

您应该尝试仅实现一种方法:

class o {
AddBall(Ball b)
}

and try to rely on polymorphism for different behavior with respect to different classes. Of course the details depend on the implementation of the Ball hierarchy.

并尝试依赖多态性来实现不同类的不同行为。当然,细节取决于 Ball 层次结构的实现。

回答by Tom Hawtin - tackline

You might (or might not) want (part of) the visitor pattern.

您可能(或可能不)想要(部分)访问者模式。

Add a method to Ball:

添加一个方法到Ball

public abstract void addTo(o o);

Implementat in LegalBalland IllegalBallas

LegalBallIllegalBall作为

public void addTo(o o) {
    o.add(this);
}

回答by Johannes Schaub - litb

Use the visitor pattern. Doing it without is cumbersome, and was subject of this question: Work around Java's static method dispatching without Double Dispatch/Visitor patterns.

使用访问者模式。不使用它很麻烦,并且是这个问题的主题:Workaround Java's static method dispatching without Double Dispatch/Visitor patterns

However, can you please state your original problem? I mean, why do you need to have those two overloads for the Add method? Maybe you can solve it in a completely different way which doesn't need to rely on dynamic dispatch like the visitor pattern?

但是,你能说出你最初的问题吗?我的意思是,为什么您需要为 Add 方法提供这两个重载?也许您可以以完全不同的方式解决它,而无需像访问者模式那样依赖动态调度?

回答by Yuliy

Well there's the visitor pattern, as mentioned above. If you can't or don't want to modify Ball, LegalBall, or IllegalBall, then you might try having a single method branch based on on the type of ball. Note that if you later add a QuasiLegalBall, this code will break. The general case that you mention is difficult because the existence of LegalBall and IllegalBall doesn't prevent there being Balls that don't fit into the two types you described (from the language's perspective, at least).

好吧,正如上面提到的那样,就是访问者模式。如果您不能或不想修改 Ball、LegalBall 或 IllegalBall,那么您可以尝试使用基于球类型的单一方法分支。请注意,如果您稍后添加 QuasiLegalBall,此代码将中断。您提到的一般情况很困难,因为 LegalBall 和 IllegalBall 的存在并不能阻止不适合您描述的两种类型的球(至少从语言的角度来看)。

class o {
    public void AddBall(Ball b) 
    { 
        if (b instanceof LegalBall) {AddLegalBall(b); }
        else if (b instanceof IllegalBall) {AddIllegalBall(b); }
        else { /*error, new type of ball created*/ }
    }
    private void AddLegalBall(LegalBall b) { }
    private void AddIllegalBall(IllegalBall b) { }
    }
 }

回答by OscarRyz

I agree with the Visitor usage.

我同意访问者的用法。

Additionally if you don't have access to the Ball hierarchy ( source code access ) or simple don't feel like modifying anything there; you could modify your client class and decide from there.

此外,如果您无权访问 Ball 层次结构(源代码访问)或简单的,请不要在那里修改任何内容;您可以修改您的客户端类并从那里决定。

The bad thing of course is you'll end up with many if/elseif statements.

坏处当然是你最终会得到很多 if/elseif 语句。

You'll need to add the generic method ( add( Ball )) and from there call the others. This is quick, easy and dirty.

您需要添加通用方法(add( Ball ))并从那里调用其他方法。这是快速,简单和肮脏的。

:)

:)

public class Test {
    public static void main( String [] args ) { 
        Ball ball = new IllegalBall();
        Test test = new Test();
        test.add( ball );
        test.add( new IllegalBall() );
        test.add( new LegalBall() );
    }
    private void add( Ball ball ){
        System.out.println("Generic method: I'll have someone handling this : "  + ball );
        if( ball instanceof IllegalBall ) {
            add( ( IllegalBall ) ball );
        } else if( ball instanceof LegalBall ) {
            add( ( LegalBall ) ball );
        }
    }
    private void add( IllegalBall ball ){
        System.out.println("illega-ball: I won't do anything about it! " + ball );
    }
    private void add( LegalBall ball ) { 
        System.out.println("legal-ball: Hey this is legal I'll do my best!! " + ball );
    }
}

class Ball {}
class IllegalBall extends Ball {}
class LegalBall extends Ball {}

BTW if you don't have the reference directly the compiler will send it to the correct method as in the last 2 calls.

顺便说一句,如果您没有直接引用,编译器会将其发送到正确的方法,如最后 2 次调用。

As you can see you just need to add the following code:

如您所见,您只需要添加以下代码:

private void add( Ball ball ){
    System.out.println("Generic method: I'll have someone handling this : "  + ball );
    if( ball instanceof IllegalBall ) {
        add( ( IllegalBall ) ball );
    } else if( ball instanceof LegalBall ) {
        add( ( LegalBall ) ball );
    }
}

回答by eljenso

The Visitor pattern, and similar solutions using callbacks, in this case only seem to try to bend your code in such a way to get the compiler to accept your flawed class hierarchy.

访问者模式和使用回调的类似解决方案在这种情况下似乎只是试图以这种方式弯曲您的代码,以使编译器接受您有缺陷的类层次结构。

I would keep type Ball, and make legal/illegal a property of that type. You would only have o.add(Ball), in which you check for legal/illegal based on some properties or through a method, isLegal() for example.

我会保留类型 Ball,并使合法/非法成为该类型的属性。您将只有 o.add(Ball),您可以在其中根据某些属性或通过方法检查合法/非法,例如 isLegal()。

If the above approach does not seem reasonable, then it is not reasonable to have a single method to add two (very) distinct types, and the subtyping relationship you proposed would not be the way to go.

如果上述方法看起来不合理,那么使用单一方法添加两个(非常)不同的类型是不合理的,并且您提出的子类型关系也不是要走的路。