5

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

           Ball
          /    \
  LegalBall    IllegalBall

我有两种方法:

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

在另一堂课上,我想做以下事情:

o.AddBall(myBall);

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

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

谢谢

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

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

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

4

7 回答 7

6

您可以使用访问者模式

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");
    }
}
于 2008-12-26T21:46:25.170 回答
4

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

class o {
AddBall(Ball b)
}

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

于 2008-12-26T21:39:27.510 回答
0

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

将方法添加到Ball

public abstract void addTo(o o);

实施于LegalBallIllegalBall作为

public void addTo(o o) {
    o.add(this);
}
于 2008-12-26T21:42:23.260 回答
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) { }
    }
 }
于 2008-12-26T22:12:53.667 回答
0

使用访客模式。不这样做很麻烦,并且是这个问题的主题: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?

于 2008-12-26T23:05:10.847 回答
-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 {}

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

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

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 );
    }
}
于 2008-12-26T22:16:31.647 回答
-1

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

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

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

于 2008-12-26T22:21:40.203 回答