如何为两个不同的子类创建超类
How can I create a SuperClass for two different SubClasses
想象一下这样的事情:
我有两个 类:
节点A和节点B。
NodeA 存储一个 Integer 并有一个 getter 方法。
NodeB 没有。
现在我想创建一个超类节点,
可以调用 getter-方法。
但是我不希望 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。 NormalCards 有一个 Value,而 Jokes 没有。我想要一个超类的原因是我可以创建一个列表
假设您想遍历列表并对所有值求和。
由于 Jokes 没有值,我必须检查 Card 是否是 Joker。如果不将其转换为 NormalCard 并获取值。 e 我的老师说,演员表是邪恶的....所以我正在寻找替代方案。
简短的回答是:你不知道。
稍微长一点的回答:如果你觉得有必要这样做,你应该改进你的设计。这违反了 OO 设计原则,尤其是 LSP.
只是成像有这样的方法:
void printValue(Node node) {
System.out.println(node.getValue());
}
您如何知道这是否有效?在运行时它可能会抛出异常,它可能会工作,谁知道呢,这显然很糟糕。
您可能更想创建一个界面
public interface ValueProvider {
Integer getValue();
}
并且只为 NodeA
实施。鉴于您的纸牌游戏示例,其中值可能是可选的,您 可以 考虑 returning null
in getValue
of NodeB
.稍微好一点的方法可能是使用 Optional<Integer>
作为 getValue()
.
的 return 类型
然后你可以在 NodeA
中使用一个方法,例如:
@Override
public Optional<Integer> getValue() {
return Optional.of(this.value);
}
并在 NodeB
@Override
public Optional<Integer> getValue() {
return Optional.empty();
}
在基本层面上,
你的设计是错误的;
你正在打破封装。
我称之为 LRN2OOP
与其循环遍历卡片集合并将值相加,
您应该遍历卡片集合并将每张卡片的值添加到累加器。
具体来说,
卡片 class 的客户端不需要了解卡片值的内部表示(这是访客模式)。
这不是一个很好的解决方案,
但这是一个代码示例:
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
}
}
如果可能的话,我肯定会在这里重新评估您的设计策略。使用单个 class 并简单地 returning 0 for Joker 比您尝试做的要容易得多。
但是,如果出于某种原因这不是一个选项,那么接口将是一个不错的选择。创建一个 Card
接口并让两个 class 实现它。请注意在 return 类型中使用 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;}
}
现在我们可以创建 class 来存储卡片 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());
}
}
这个问题的解决方案是不创建超类。你没问题:这是糟糕的设计。
我们对其进行了更改并创建了一个 class 卡片,其中包含两个 静态工厂方法 :
创建小丑()
createNormalCard(int 值)
感谢您的所有回答。
你在几周内学到了很多东西。
想象一下这样的事情: 我有两个 类: 节点A和节点B。 NodeA 存储一个 Integer 并有一个 getter 方法。 NodeB 没有。
现在我想创建一个超类节点, 可以调用 getter-方法。 但是我不希望 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。 NormalCards 有一个 Value,而 Jokes 没有。我想要一个超类的原因是我可以创建一个列表
假设您想遍历列表并对所有值求和。
由于 Jokes 没有值,我必须检查 Card 是否是 Joker。如果不将其转换为 NormalCard 并获取值。 e 我的老师说,演员表是邪恶的....所以我正在寻找替代方案。
简短的回答是:你不知道。
稍微长一点的回答:如果你觉得有必要这样做,你应该改进你的设计。这违反了 OO 设计原则,尤其是 LSP.
只是成像有这样的方法:
void printValue(Node node) {
System.out.println(node.getValue());
}
您如何知道这是否有效?在运行时它可能会抛出异常,它可能会工作,谁知道呢,这显然很糟糕。
您可能更想创建一个界面
public interface ValueProvider {
Integer getValue();
}
并且只为 NodeA
实施。鉴于您的纸牌游戏示例,其中值可能是可选的,您 可以 考虑 returning null
in getValue
of NodeB
.稍微好一点的方法可能是使用 Optional<Integer>
作为 getValue()
.
然后你可以在 NodeA
中使用一个方法,例如:
@Override
public Optional<Integer> getValue() {
return Optional.of(this.value);
}
并在 NodeB
@Override
public Optional<Integer> getValue() {
return Optional.empty();
}
在基本层面上, 你的设计是错误的; 你正在打破封装。 我称之为 LRN2OOP
与其循环遍历卡片集合并将值相加, 您应该遍历卡片集合并将每张卡片的值添加到累加器。 具体来说, 卡片 class 的客户端不需要了解卡片值的内部表示(这是访客模式)。
这不是一个很好的解决方案, 但这是一个代码示例:
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
}
}
如果可能的话,我肯定会在这里重新评估您的设计策略。使用单个 class 并简单地 returning 0 for Joker 比您尝试做的要容易得多。
但是,如果出于某种原因这不是一个选项,那么接口将是一个不错的选择。创建一个 Card
接口并让两个 class 实现它。请注意在 return 类型中使用 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;}
}
现在我们可以创建 class 来存储卡片 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());
}
}
这个问题的解决方案是不创建超类。你没问题:这是糟糕的设计。
我们对其进行了更改并创建了一个 class 卡片,其中包含两个 静态工厂方法 : 创建小丑() createNormalCard(int 值)
感谢您的所有回答。 你在几周内学到了很多东西。