Java 根据2个输入参数的子类型更改方法行为
我试图创建一个干净的类设计的纸牌游戏。 我想比较两张卡片并返回“值”最高的那张 我有一个抽象卡片类和从中继承的两个类:Java 根据2个输入参数的子类型更改方法行为,java,oop,design-patterns,Java,Oop,Design Patterns,我试图创建一个干净的类设计的纸牌游戏。 我想比较两张卡片并返回“值”最高的那张 我有一个抽象卡片类和从中继承的两个类: public abstract class Card { ... //common method public int getCardValue() { return this.cardValue; } //comparison methods public abstract Card compare(Colo
public abstract class Card {
...
//common method
public int getCardValue() { return this.cardValue; }
//comparison methods
public abstract Card compare(ColoredCard card);
public abstract Card compare(TrumpCard card);
}
public class ColoredCard extends Card {
//specific attribute
private Color cardColor;
...
//specific method
public Color getColor() { return this.cardColor; }
public Card compare(ColoredCard card) {
if(this.getColor() == card.getColor())
return this.getCardValue() > card.getCardValue() ? this : card;
return this;
}
public Card compare(TrumpCard card) {
return card;
}
}
public class TrumpCard extends Card {
...
public Card compare(ColoredCard card) {
return this;
}
public Card compare(TrumpCard card) {
return this.getCardValue() > card.getCardValue() ? this : card;
}
}
但每当我尝试时,它仍然会抛出一个错误:
Card c = new ColoredCard(5);
Card c2 = new TrumpCard(1);
c.compareTo(c2); //error method compareTo not applicable to type of argument "Card"
我需要访问整个子类接口来执行我的每个比较,但也要保持比较调用“generic”(通过卡超类)
如果可能,我希望避免使用instanceOf
指令或反射
谢谢,如果可能的话,我会在基类上定义一个抽象方法,让子类提供它们的绝对值。然后,您可以使基类
具有可比性
,并实现使用此值的compareTo()
方法。价值甚至不需要公开披露
public static abstract class Card implements Comparable<Card> {
@Override
public int compareTo(Card other) {
return Integer.compare(this.value(), other.value());
}
protected abstract int value();
}
public static class ColoredCard extends Card {
@Override
protected int value() {
return 1;
}
}
public static class TrumpCard extends Card {
@Override
protected int value() {
return 10;
}
}
public static void main(String... args) throws Exception {
System.out.println(new TrumpCard().compareTo(new ColoredCard()));
System.out.println(new ColoredCard().compareTo(new TrumpCard()));
}
如果可能的话,我会在基类上定义一个抽象方法,让子类提供它们的绝对值。然后,您可以使基类
具有可比性
,并实现使用此值的compareTo()
方法。价值甚至不需要公开披露
public static abstract class Card implements Comparable<Card> {
@Override
public int compareTo(Card other) {
return Integer.compare(this.value(), other.value());
}
protected abstract int value();
}
public static class ColoredCard extends Card {
@Override
protected int value() {
return 1;
}
}
public static class TrumpCard extends Card {
@Override
protected int value() {
return 10;
}
}
public static void main(String... args) throws Exception {
System.out.println(new TrumpCard().compareTo(new ColoredCard()));
System.out.println(new ColoredCard().compareTo(new TrumpCard()));
}
所以我找到了一种使用访问者模式的方法:
public interface ICardVisitor {
public Card visit(TrumpCard card);
public Card visit(ColoredCard card);
public void setSecondCard(ColoredCard card);
public void setSecondCard(TrumpCard card);
}
public class ComparisonVisitor implements ICardVisitor {
private TrumpCard trumpCard;
private ColoredCard coloredCard;
...
//contains comparison logic & instances of card subtypes
}
我还必须在我的抽象卡类中添加一个额外的函数(除了经典的accept(Visitor v)方法):
public abstract void setThisCardAsParameter(ICardVisitor v);
在具体的卡实现中:
public Card accept(ICardVisitor visitor) {
return visitor.visit(this);
}
public void setThisCardAsParameter(ICardVisitor v) {
v.setSecondCard(this);
}
通过这种方式,比较类知道每张卡的每个子类型,因此他可以访问给定子类的所有特定方法。
电话如下所示:
public static void main(String [] args) {
ICardVisitor cmp = new ComparisonVisitor();
Card c = new TrumpCard(1);
Card c2 = new ColoredCard(CardTypes.SPADES,1);
ICardVisitor cmp = new ComparisonVisitor();
c.setThisCardAsParameter(cmp);
Card winningCard = c2.accept(cmp);
}
如果设计不好或者可以改进,请告诉我 所以我找到了一种使用访问者模式的方法:
public interface ICardVisitor {
public Card visit(TrumpCard card);
public Card visit(ColoredCard card);
public void setSecondCard(ColoredCard card);
public void setSecondCard(TrumpCard card);
}
public class ComparisonVisitor implements ICardVisitor {
private TrumpCard trumpCard;
private ColoredCard coloredCard;
...
//contains comparison logic & instances of card subtypes
}
我还必须在我的抽象卡类中添加一个额外的函数(除了经典的accept(Visitor v)方法):
public abstract void setThisCardAsParameter(ICardVisitor v);
在具体的卡实现中:
public Card accept(ICardVisitor visitor) {
return visitor.visit(this);
}
public void setThisCardAsParameter(ICardVisitor v) {
v.setSecondCard(this);
}
通过这种方式,比较类知道每张卡的每个子类型,因此他可以访问给定子类的所有特定方法。
电话如下所示:
public static void main(String [] args) {
ICardVisitor cmp = new ComparisonVisitor();
Card c = new TrumpCard(1);
Card c2 = new ColoredCard(CardTypes.SPADES,1);
ICardVisitor cmp = new ComparisonVisitor();
c.setThisCardAsParameter(cmp);
Card winningCard = c2.accept(cmp);
}
如果设计不好或者可以改进,请告诉我 不应该只接受两张
卡片compare
吗?不,因为每次比较我都需要访问我的子类的具体方法。那么,你设计类的方式就有问题了。这将有助于了解相关部分是如何实现的,以及您希望如何比较它们。换句话说,compare
方法不必知道如何根据两张卡的类型进行比较。它应该是卡
类型,公开比较器
方法,并且它应该能够自己处理不同类型的卡。好的,感谢您的反馈!我已经在我的原始帖子中添加了一些关于我的课程设计的附加信息。我会尝试你的设计建议,并保持这个线程更新!我做了你推荐的。似乎我必须在我的每个卡片子类中实现每个“compare(CardSubtype card)”方法!不应该只接受两张卡片compare
吗?不,因为每次比较我都需要访问我的子类的具体方法。那么,你设计类的方式就有问题了。这将有助于了解相关部分是如何实现的,以及您希望如何比较它们。换句话说,compare
方法不必知道如何根据两张卡的类型进行比较。它应该是卡
类型,公开比较器
方法,并且它应该能够自己处理不同类型的卡。好的,感谢您的反馈!我已经在我的原始帖子中添加了一些关于我的课程设计的附加信息。我会尝试你的设计建议,并保持这个线程更新!我做了你推荐的。似乎我必须在我的每个卡片子类中实现每个“compare(CardSubtype card)”方法!谢谢,但是这样不行。在每种情况下,我都需要使用特定的子类方法来比较卡片-我不能简单地比较valuesOkay,因此没有办法根据两个卡片子类型自动分配到给定的比较方法?使用“Kind”enum的解决方案很容易实现,应该可以工作,但我觉得它并不好:它是一个重复的信息,因为每个子类总是有一个不同的“Kind”(等价关系)。正如我提到的,有一种方法可以在没有instanceof
的情况下进行调度,您可以使用Visitor模式将重载方法(每种卡类型一个)分派给访问者。但我从来没有觉得它特别优雅。谢谢,但这行不通。在每种情况下,我都需要使用特定的子类方法来比较卡片-我不能简单地比较valuesOkay,因此没有办法根据两个卡片子类型自动分配到给定的比较方法?使用“Kind”enum的解决方案很容易实现,应该可以工作,但我觉得它并不好:它是一个重复的信息,因为每个子类总是有一个不同的“Kind”(等价关系)。正如我提到的,有一种方法可以在没有instanceof
的情况下进行调度,您可以使用Visitor模式将重载方法(每种卡类型一个)分派给访问者。但我从未觉得它特别优雅。