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

Java 将超类作为参数传递给需要子类的方法,java,inheritance,methods,polymorphism,overloading,Java,Inheritance,Methods,Polymorphism,Overloading,我有一个对象树,看起来像 Ball / \ LegalBall IllegalBall 我有两种方法: class o { AddBall(LegalBall l) AddBall(IllegalBall i) } 在另一节课上,我想做以下几点: o.AddBall(myBall); 其中myBall属于Ball类型。 并让它根据子类型调用正确的方法。 显然我不能这么做。。。这些论点不适用 有人知道我怎样才能达到我想要的吗?或者,如

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

           Ball
          /    \
  LegalBall    IllegalBall
我有两种方法:

class o {
AddBall(LegalBall l)
AddBall(IllegalBall i)
}
在另一节课上,我想做以下几点:

o.AddBall(myBall);
其中myBall属于Ball类型。 并让它根据子类型调用正确的方法。 显然我不能这么做。。。这些论点不适用

有人知道我怎样才能达到我想要的吗?或者,如果有一个很好的工作

谢谢

编辑:我试图构建的应用程序是一个板球记分卡类型的东西。因此,根据投球的类型,其他各种元素也应该改变

我的初衷是能够从某种形式的UI中指定球的类型和得分,然后从球厂中创建一个合适的类型球,例如,当我向球队得分发送一个无球时,它会将值添加到球队得分中,但也会将值添加到无球计数器中。但是当我把同样的球交给巴特斯门分析来处理时,它应该只给巴特斯门的总得分1分


我希望这不是对我的初衷的太糟糕的解释。

您应该尝试只实施一种方法:

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

您可能(也可能不)想要(部分)访客模式

将方法添加到
Ball

public abstract void addTo(o o);
legaball
IllegalBall
中实现

public void addTo(o o) {
    o.add(this);
}
你可以用这个

或者更一般地说:

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

正如上面提到的,这里有访客模式。如果您不能或不想修改Ball、LegalBall或IllegalBall,那么您可以尝试根据Ball的类型使用单个方法分支。请注意,如果稍后添加一个拟代数球,则此代码将中断。你提到的一般情况是困难的,因为LegalBall和IllegalBall的存在并不能阻止出现不符合你描述的两种类型的球(至少从语言的角度来看)


我同意访客的习惯

此外,如果您没有访问Ball层次结构(源代码访问)或simple的权限,则不想在那里修改任何内容;您可以修改客户机类并从中做出决定

当然,糟糕的是,最终会出现许多if/elseif语句

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

:)

顺便说一句,如果您没有直接引用,编译器将把它发送到前两次调用中的正确方法

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

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

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

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


如果上述方法似乎不合理,那么使用一个方法添加两个(非常)不同的类型是不合理的,并且您提出的子类型关系将不是一条可行的道路。

使用访问者模式。不做这件事很麻烦,而且是这个问题的主题:


然而,你能说明你原来的问题吗?我是说,为什么Add方法需要这两个重载?也许你可以用一种完全不同的方式来解决这个问题,而不需要像访问者模式那样依赖于动态调度?

我需要将球添加到更多的对象中,而不仅仅是篮子。我需要为我想要添加ball的每种类型实现一个方法吗?在一个正常的接口中添加“visit”和“accept”方法是非常奇怪的。这是一个教科书上的例子,说明了“instanceof”和方法重载是如何导致糟糕设计的代码味道。你在滥用打字系统。
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");
    }
}
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) { }
    }
 }
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 {}
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 );
    }
}