如何为两个不同的子类创建超类
Posted
技术标签:
【中文标题】如何为两个不同的子类创建超类【英文标题】:How can I create a SuperClass for two different SubClasses 【发布时间】:2019-01-04 15:21:25 【问题描述】:想象一下: 我有两节课: 节点 A 和节点 B。 NodeA 存储一个 Integer 并具有一个 getter 方法。 NodeB 没有。
现在我想创建一个超类节点, 它可以调用getter-Method。 但是我不希望 NodeB 存储一个整数。 我该如何处理?
下面是我的代码, NodeB 抛出异常。 超类 Node 有一个 Optinal。
public abstract class Node
public Integer getValue();
public class NodeA extends Node
public Integer value;
public NodeA()
@Override
public Integer getValue()
return this.value;
public class NodeB extends Node
public NodeB()
@Override
public Integer getValue()
throw new Exception();
编辑:此处添加了以下虚假答案的解释。
我的工作是创建一个纸牌游戏。我有 NormalCards 和 Jokers。 NormalCard 有一个价值,而笑话则没有。我想要一个超类的原因是我可以创建一个列表
假设您想遍历列表并对所有值求和。
由于笑话没有价值,我必须检查卡片是否是小丑。如果不将其转换为 NormalCard 并获取值。 e 我的老师说,演员阵容是邪恶的......所以我正在寻找替代方案。
【问题讨论】:
你应该如何处理?很难回答关于不好的实践案例的“最佳实践”问题......超类的目标是包含子类中的共同点,或者强制子类使用“模式”。如果您的目标是不尊重这个超类,那么创建一个超类会很奇怪。 你所有的卡片都有价值。小丑的价值与其他所有卡片的价值不同。也许使用零 (0) 作为百搭值。 【参考方案1】:简短的回答是:你没有。
稍微长一点的答案:如果您觉得有必要这样做,您应该改进您的设计。这违反了OO设计原则,尤其是LSP。
使用这样的方法进行成像:
void printValue(Node node)
System.out.println(node.getValue());
您如何知道这是否会起作用?在运行时它可能会抛出异常,它可能会起作用,谁知道呢,这显然很糟糕。
你可能更想要的是创建一个界面
public interface ValueProvider
Integer getValue();
并且仅针对NodeA
实现此功能。鉴于您的纸牌游戏示例,其中值可能是可选的,您可以考虑在 getValue
的 NodeB
中返回 null
。更好的方法可能是使用Optional<Integer>
作为getValue()
的返回类型。
然后你可以在NodeA
中有一个方法,比如:
@Override
public Optional<Integer> getValue()
return Optional.of(this.value);
在NodeB
@Override
public Optional<Integer> getValue()
return Optional.empty();
【讨论】:
我的问题措辞不好。我努力做得更好。 @FelixHohnstein 我已更新以回答您的纸牌游戏示例【参考方案2】:在基本层面上, 你的设计是错误的; 你正在打破封装。 我称之为LRN2OOP
而不是循环遍历一组卡片并将值相加, 您应该遍历卡片集合,并让每张卡片将其价值添加到累加器中。 具体来说, Card 类的客户端不需要知道 Card 值的内部表示(这是访问者模式)。
这不是一个很好的解决方案, 但这是一个代码示例:
public interface CardScoreBlammy
void addToScore(int cardScore);
public interface MyCard
void accumulateScore(ScoreBlammy);
... other shared Card functionality.
public class CardHolder
implements CardScoreBlammy
private int accumumatedScore = 0;
private List<MyCard> cardList;
... populate the cardList somehow.
public void addToScore(final int cardScore)
accumulatedScore += cardScore;
public int getScoreTotal()
accumulatedScore = 0;
for (final MyCard currentCard : cardList)
currentCard.accumulateScore(this);
return accumulatedScore;
public class NotAJoker
implements MyCard
private int myValue;
public void accumulateScore(final ScoreBlammy scoreBlammy)
scoreBlammy.addToScore(myValue)
public class IRJoker
implements MyCard
public void accumulateScore(final ScoreBlammy scoreBlammy)
// do nothing
【讨论】:
【参考方案3】:如果可能的话,我肯定会在这里重新评估您的设计策略。使用单个类并为 Joker 简单地返回 0 比您尝试做的要容易得多。
但是,如果由于某种原因这不是一个选项,那么接口将是一个不错的选择。创建一个Card
接口并让两个类都实现它。注意在返回类型中使用Integer
而不是int
以允许空值。此外,由于您已经知道非百搭牌的所有可能值,因此枚举可以很好地定义它:
public interface Card
public Integer getValue();
public class Joker implements Card
@Override
public Integer getValue()
return null;
public class NotJoker implements Card
private CARD_TYPE cardType;
public NotJoker(CARD_TYPE type)
this.cardType = type;
public CARD_TYPE getType()
return cardType;
@Override
public Integer getValue()
return cardType.getValue();
public enum CARD_TYPE
ACE(11), KING(10), QUEEN(10), JACK(10),
TEN(10), NINE(9), EIGHT(8), SEVEN(7),
SIX(6), FIVE(5), FOUR(4), THREE(3),
TWO(2);
private final int value;
CARD_TYPE(int value)
this.value = value;
public int getValue() return value;
现在我们可以创建我们的类来存储卡片,Deck
。我们只对所有卡片使用card.getValue()
,并检查生成的Integer
是否为null
,然后再添加它的值:
public class Deck
private ArrayList<Card> cardList;
public Deck()
cardList = new ArrayList<Card>();
public void addCard(Card card)
cardList.add(card);
public int getTotalScore()
int totalScore = 0;
for(Card card : cardList)
Integer value = card.getValue();
if(value != null)
totalScore += value;
return totalScore;
这里有一个快速测试来证明它有效:
public class CardGame
public static void main(String[] args)
Deck deck = new Deck();
deck.addCard(new Joker());
deck.addCard(new NotJoker(CARD_TYPE.FIVE));
deck.addCard(new NotJoker(CARD_TYPE.FOUR));
deck.addCard(new NotJoker(CARD_TYPE.ACE));
deck.addCard(new NotJoker(CARD_TYPE.KING));
deck.addCard(new Joker());
deck.addCard(new NotJoker(CARD_TYPE.SEVEN));
//total score: 37
System.out.println("total score: " + deck.getTotalScore());
【讨论】:
【参考方案4】:这个问题的解决方案是不要创建超句。你没问题:这是糟糕的设计。
我们对其进行了更改,并使用两个静态工厂方法创建了一个类 Card: 创建小丑() createNormalCard(int value)
感谢您的所有回答。 几周后你会学到很多东西。
【讨论】:
以上是关于如何为两个不同的子类创建超类的主要内容,如果未能解决你的问题,请参考以下文章
Xcode:如何为指向两个不同团队帐户(企业和公司)的两个不同目标选择两个不同的应用程序组