将超类作为参数传递给期望子类的方法

时间:2008-12-26 21:32:32

标签: java inheritance methods polymorphism overloading

我有一个类似于

的对象树
           Ball
          /    \
  LegalBall    IllegalBall

我有两种方法:

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

在另一个课程中,我想做以下几点:

o.AddBall(myBall);

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

有谁知道我怎么能达到我的目的?或者,如果有一个好的工作

由于

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

我的初衷是能够指定球类型并从某种形式的UI中得分,然后从BallFactory创建一个合适的类型球,然后例如当我向团队得分发送一个无球时它会添加球队得分上的值,但也将值添加到无球计数器。但是当我向Batsmens Analysis提供相同的球来处理它时,它应该只能在击球手总数上得到-1值。

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

8 个答案:

答案 0 :(得分:6)

您可以使用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);
    }
}

或使其更通用:

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

答案 1 :(得分:3)

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

class o {
AddBall(Ball b)
}

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

答案 2 :(得分:0)

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

Ball添加方法:

public abstract void addTo(o o);

LegalBallIllegalBall中实现

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

答案 3 :(得分:0)

如上所述,有访客模式。如果您不能或不想修改Ball,LegalBall或IllegalBall,那么您可以尝试根据球的类型设置单个方法分支。请注意,如果您稍后添加QuasiLegalBall,则此代码将中断。您提到的一般情况很难,因为LegalBall和IllegalBall的存在并不能防止Balls不适合您描述的两种类型(至少从语言的角度来看)。

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

答案 4 :(得分:0)

使用访客模式。没有这样做很麻烦,并且是这个问题的主题:Work around Java's static method dispatching without Double Dispatch/Visitor patterns

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

答案 5 :(得分:-1)

你怎么能指望它知道打哪一个?是什么让这两种方法分开,你希望它可以调用一种而不是另一种?

答案 6 :(得分:-1)

我同意访问者的使用情况。

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

糟糕的是,你最终会得到许多if / elseif语句。

您需要添加通用方法( 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如果您没有直接引用,编译器会将其发送到正确的方法,就像在最后两次调用中一样。

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

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

答案 7 :(得分:-1)

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

我会保留类型Ball,并使合法/非法属于该类型的财产。您只有o.add(Ball),您可以根据某些属性或方法检查合法/非法,例如isLegal()。

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