简体   繁体   English

如何为两个不同的子类创建一个超类

[英]How can I create a SuperClass for two different SubClasses

Imagine sth like this: I have two classes: NodeA and NodeB. 想象一下:我有两个类:NodeA和NodeB。 NodeA stores an Integer and has a getter-method. NodeA存储一个Integer并具有一个getter方法。 NodeB doesn't. NodeB没有。

Now I want to create a Superclass Node, which can call the getter-Method. 现在,我想创建一个可以调用getter-Method的超类节点。 However I don't want NodeB to store an Integer. 但是我不希望NodeB存储一个整数。 How should I handle this? 我该如何处理?

With my code below, NodeB throws an Exception. 在下面的代码中,NodeB引发异常。 The superclass Node has an 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();
    }
}

Edit: Explanation from faux answer below added here. 编辑:从下面的人造答案的解释在这里添加。

My Job is to create a Card game. 我的工作是创建纸牌游戏。 I have NormalCards and Jokers. 我有NormalCards和Jokers。 The NormalCards have a Value, the Jokes dont. 普通卡有一个值,笑话没有。 The reason I want a Superclass is so I can create a List 我想要一个超类的原因是可以创建一个列表

Imagine you want to travers the List and sume all Values. 假设您要遍历列表并求和所有值。

Since Jokes have no values, I have to check wheter a Card is a Joker. 由于笑话没有价值,因此我必须检查卡片是否为笑话。 If not cast it to a NormalCard and get the Value. 如果没有,则将其强制转换为NormalCard并获取该值。 e My Teacher said,that casts are evil....so I am looking for an alternative. 我的老师说,演员阵容是邪恶的。...所以我在寻找替代品。

Short answer is: You don't. 简短的答案是:您不会。

Slightly longer answer: If you feel the need to do this, you should improve your design. 稍长的答案:如果您认为需要这样做,则应该改进设计。 This violates OO design principles, especially the LSP . 这违反了OO设计原则,尤其是LSP

Just imaging having a method like this: 只是成像具有这样的方法:

void printValue(Node node) {
   System.out.println(node.getValue());
}

How are you going to know whether or not this will work? 您将如何知道这是否有效? At runtime it might throw an exception, it might work, who knows, which is clearly bad. 在运行时,它可能会引发异常,它可能会起作用,谁知道呢,这显然是不好的。

What you maybe rather want is to create an interface 您可能想要的是创建一个界面

public interface ValueProvider {
   Integer getValue();
}

and only implement this for NodeA . 并且仅针对NodeA实现此功能。 Given your example of a card game where the value might be optional, you could consider returning null in getValue of NodeB . 在您的纸牌游戏示例中,值可能是可选的,您可以考虑在NodeB getValue中返回null A slightly better approach might be to use Optional<Integer> as a return type for getValue() . 更好的方法可能是使用Optional<Integer>作为getValue()的返回类型。

Then you can have a method in NodeA like: 然后,您可以在NodeA拥有一个方法,例如:

@Override   
public Optional<Integer> getValue() {
    return Optional.of(this.value);
}

and in NodeB NodeB

@Override   
public Optional<Integer> getValue() {
    return Optional.empty();
}

At a basic level, you're design is wrong; 从根本上说,您的设计是错误的。 you are breaking encapsulation. 您正在破坏封装。 I call this LRN2OOP 我称它为LRN2OOP

Instead of looping through a collection of cards and adding up the value, you should loop through the collection of cards and have each card add its value to an accumulator. 您不应遍历卡片集合并累加值,而应遍历卡片集合并使每张卡片将其值添加到累加器中。 Specifically, there is no need for the client of the Card class to know about the internal representation of the Card value (this is the Visitor pattern). 特别是,Card类的客户端不需要了解Card值的内部表示(这是Visitor模式)。

This is not a great way solution, but here is a code example: 这不是一个很好的解决方案,但是下面是一个代码示例:

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
  }
}

I would definitely re-evaluate your design strategy here if possible. 如果可能的话,我绝对会在这里重新评估您的设计策略。 Using a single class and simply returning 0 for Joker is so much easier than what you are trying to do. 使用单个类并为Joker简单地返回0比您尝试做的要容易得多。

If, however, that is not an option for some reason, then an interface would be a good option. 但是,如果由于某种原因这不是一个选择,那么接口将是一个不错的选择。 Create a Card interface and have both classes implement it. 创建一个Card接口,并让两个类都实现它。 Note the use of Integer and not int in the return type to allow for null values. 请注意,在返回类型中使用Integer而不是int允许空值。 Also, since you already know all the possible values for a non-joker card an enum works well for defining that: 另外,由于您已经知道非百搭牌的所有可能值,因此枚举可很好地定义:

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;}
}

Now we can create our class to store the cards, Deck . 现在,我们可以创建存储卡Deck We just use card.getValue() for all Cards, and check whether the resulting Integer is null before we add its value: 我们只对所有Card使用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;
    }
}

And here is a quick test to prove it works: 这是一个快速测试以证明它有效:

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());
    }

}

The solution for this Problem was to dont create a superclase. 解决此问题的方法是不创建超级句。 You were all right: This was bad Design. 您没事:这是糟糕的设计。

We changed it and create one class Card with two static factory methods : createJoker() createNormalCard(int value) 我们对其进行了更改,并使用两个静态工厂方法创建了一个类Card:createJoker()createNormalCard(int value)

Thanks for all your answers. 感谢您的所有答复。 You learn a lot in a few weeks. 您将在几周内学到很多东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何编写一种方法来轻松创建不同类型的子类 - How can I write a method to easily create different types of subclasses 我可以在超类的数组上调用子类吗? - can I call subclasses on an array of a superclass? 我是否将创建一个我永远不会仅因转换不同子类而实例化的超类? - Shall I create a Superclass I will never instance just for casting different subclasses? 在Java中,如果子类具有不同的类型,我可以以某种方式将字段移至超类吗? - In Java, can I somehow move field to superclass if subclasses have different types for them? 如何实例化超类中的子类? - How to instantiate subclasses in superclass? 我如何创建3个超抽象类,它们已经在构造函数中提供了数量不同的相似子类 - How can i create a super abstract class of 3 already present similar subclasses having different number of parameters in their constructors 可运行的子类,普通的超类,如何运行这些子类? - Runnable subclasses, ordinary superclass, how to run the subclasses? 我如何在 M 类中创建任何这些子类 - How I can create any of these subclasses inside class M 超类静态方法返回2个不同的子类 - Superclass static method returning 2 different subclasses 超类和子类 - SuperClass And subclasses
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM