PlayCard Class的Equals方法,如何工作?

时间:2015-02-20 15:52:35

标签: java oop equals

我一直在玩一个PlayingCard类,我在为类编写equals()方法时遇到了困难。 equals方法的目的是比较两张扑克牌,看它们是否相同。

我使用了Big Java Late Objects Book中的一个例子并对其进行了修改以尝试检查两张卡是否相同,但在两种情况下(相同且不相同),我得到相同的输出。出了什么问题,怎么才能让它发挥作用?

这是PlayingCard类,底部是equals方法。

public class PlayingCard
{

private Rank rank;
private Suit suit;

public PlayingCard(Rank rank, Suit suit)
{
    this.rank = rank;
    this.suit = suit;
}

public Rank getRank()
{   
    System.out.println(rank);
    return rank;
}

public Suit getSuit()
{
    System.out.println(suit);
    return suit;
}

@Override
public String toString()
{
  return getClass().getName() + "[rank " + rank + "suit " + suit + "]"; 
}

public void format()
{
    System.out.format(rank + " OF " + suit);
    System.out.println("");
}

@Override
public boolean equals(Object otherObject)
{
    if (otherObject == null)
    {
        System.out.println("Match");
        return false;
    }
    if (getClass() != otherObject.getClass())
    {
        System.out.println("Match");
        return false;
    }

    System.out.println("No Match, True");
    PlayingCard other = (PlayingCard) otherObject;
    return suit.equals(other.suit) && rank == other.rank;
}

}

这是目前的测试人员:

public class PlayingCardTester 
{
public static void main(String[] args) 
{
    PlayingCard test = new PlayingCard(Rank.ACE, Suit.DIAMONDS);
    PlayingCard test2 = new PlayingCard(Rank.FIVE, Suit.CLUBS);
    PlayingCard test3 = new PlayingCard(Rank.ACE, Suit.DIAMONDS);
    test.getRank();
    test2.getRank();
    test.getSuit();
    test2.getSuit();
    test.toString();
    test.format();
    test2.toString();
    test2.format();
    test.equals(test2);
    test.equals(test3);
    System.out.println("");
}

}

编辑:

Enum Rank:

public enum Rank 
{
TWO(2), THREE(3), FOUR(4), FIVE(5), SIX(6), SEVEN(7), EIGHT(8), NINE(9), 
TEN(10), JACK(11), QUEEN(12), KING(13), ACE(14);

private int value;

private Rank(int value)
{
    this.value = value;
}

public int getValue()
{
    return value;
}
}

Enum Suit:

public enum Suit 
{
SPADES(-2), CLUBS(-1), HEARTS(0), DIAMONDS(1);

private int value;

private Suit(int value)
{
    this.value = value;
}

public int getValue()
{
    return value;
}
}

我从测试人员得到的输出:

run:
ACE   // getRank and getSuit print out the Rank and Suit respectivly for 
FIVE  // for the card specified and return it
DIAMONDS
CLUBS
ACE OF DIAMONDS // toString and format work together to get output of
FIVE OF CLUBS   // cards to show what they are
No Match, True  // This is from the equals method, both outputs are the
No Match, True  // same, first test-test2, second test-test3.

BUILD SUCCESSFUL (total time: 1 second)

我想要做的是将PlayCard测试与test2和test3进行比较,看看它们是否是同一张卡,如同具有相同的套装和等级,并打印出它们是否相等

编辑2:当前等于方法改变,仍然只是作为两个测试的输出得到假。

    @Override
public boolean equals(Object otherObject)
{
    boolean set = false;
    if (!(otherObject instanceof PlayingCard))
    {
        set = false;
    }

    if (otherObject == this)
    {
        set = true;
    }
    System.out.println(set);
    return set;
}

3 个答案:

答案 0 :(得分:1)

这不是你想的那样:

if (getClass() != otherObject.getClass())

您在此处比较Class个对象引用。即使类具有相同的类型,它们也可能具有由各自的Class方法返回的不同getClass()对象引用。更好的是,使用instanceof运算符。

@Override
public boolean equals(Object otherObject)
{
    if (otherObject == null)
    {
        System.out.println("Match");
        return false;
    }
    if (otherObject instanceof PlayingCard)
    {
        PlayingCard other = (PlayingCard) otherObject;
        return suit.equals(other.suit) && rank == other.rank;
    }

    return false;
}

我建议查看的一个很好的例子是Java String equals()方法。那里的实施是完美的。遵循它作为指导:

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String) anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                        return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

另外,我建议您删除print语句,除非您只是出于调试目的。 equals()比较只应进行比较,而不是做其他任何事情。

答案 1 :(得分:1)

您的原始equals方法已正确实施。输出是相同的,因为无论suit.equals(other.suit) && rank == other.rank计算什么,equals方法都会打印相同的结果。

修改:您可以看到equals()方法结束时稍有变化:

PlayingCard other = (PlayingCard) otherObject;
boolean result = suit.equals(other.suit) && rank == other.rank;
System.out.println("No Match, " + result);
return result;

我建议删除print语句,并使用JUnit等测试框架测试代码。

当然,您也应该覆盖hashCode()

答案 2 :(得分:-2)

您可以为该类型的对象创建比较器。 它将是这样的:

    public class ComparatorCard<T extends PlayingCard> implements Comparator<T> {

    @Override
    public int compare(T objectOne, T ObjectTwo) { 

        return objectOne.toString().compareTo(ObjectTwo.toString()); // Change what you need where
    }
}

使用此类,您还可以通过某些使用优先级的Java结构中的订单保存PalyingCards。