传递超作为参数传递给方法,希望子类
我有一个对象树,看起来像传递超作为参数传递给方法,希望子类
Ball
/ \
LegalBall IllegalBall
而且我有2种方法:
class o {
AddBall(LegalBall l)
AddBall(IllegalBall i)
}
另一个类我想要做的如下:
o.AddBall(myBall);
其中myBall是Ball类型。 并让它根据子类型调用正确的方法。 显然我不能这样做......参数不适用。
有谁知道我怎么能达到我想要的?或者,如果有一个很好的解决办法
感谢
编辑:我试图建立的应用程序是一个板球记分卡类型的事情。所以根据被击球的球的类型,各种其他元素应该改变。
我的初衷是能够指定球的类型并运行从某种形式的UI得分,然后从BallFactory创建一个合适的类型球,然后例如当我发送一个无球球队得分时它会将该值添加到团队评分中,但也将该值添加到no ball计数器中。但是当我把同样的球给了巴茨曼分析来处理的时候,它应该只得到值-1的batsmens总数。
我希望那不是太糟糕我的初衷的解释。
您可以使用Visitor pattern:
添加方法Ball
。
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");
}
}
你如何期待它知道哪一个要打电话?两种方法的区别是什么,你会期望它叫一个而不是另一个?
你应该尝试只实现一个方法:
class o {
AddBall(Ball b)
}
,并试图依靠多态性不同的行为相对于不同类别。当然细节取决于Ball层次的实现。
您可能(或可能不)想要(部分)访问者模式。在LegalBall
和IllegalBall
public abstract void addTo(o o);
如是否履行
public void addTo(o o) {
o.add(this);
}
那么有访问者模式,如上所述。如果你不能或不想修改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) { }
}
}
我同意访客的使用。
此外,如果您没有访问球层次结构(源代码访问)或简单不觉得在那里修改任何东西;你可以修改你的客户类并从那里决定。
当然不好的事情是你会得到很多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);
}
}
访问者模式,以及类似的解决方案使用回调,在这种情况下,似乎只是尽量弯曲你的代码,以这样的方式来让编译器接受你有缺陷的类层次结构。
我会保持类型球,并使该类型的属性合法/非法。你只有o.add(Ball),你可以根据某些属性或方法检查合法/非法,例如isLegal()。
如果上述方法看起来不合理,那么添加两个(非常)不同类型的单一方法是不合理的,并且您提出的子类型关系不会成为可行的方法。
使用访问者模式。这样做不麻烦,而且是这个问题的主题:Work around Java's static method dispatching without Double Dispatch/Visitor patterns。
但是,您能否说明您的原始问题?我的意思是,为什么你需要为Add方法重载这两个重载?也许你可以用完全不同的方式解决它,而不需要像访问者模式那样依赖动态调度?
我将需要添加到不止篮子,虽然,一些其他的对象。我需要为每个我想要添加球的类型实现一个方法吗? – Rocco 2008-12-26 21:52:11
更新了一般情况。 – dalle 2008-12-26 21:53:01