Reputation: 94
I would like to prevent the insertion of an object in a Set if an object of the same type is already in. Example :
If i have following class :
public class Card{...}
public class Clubs extends Card{...}
public class Diamonds extends Card{...}
public class Hearts extends Card{...}
public class Spades extends Card{...}
The behavior should be :
Set<Card> cards = new HashSet<>();
System.out.println(cards.add(new Diamonds()) //prints "true"
System.out.println(cards.add(new Spades()) //prints "true"
System.out.println(cards.add(new Spades()) //prints "false"
Is there a simple way or a set implementation which can give me this behavior ?
I thought about overriding hashcode/equals for each class extending Card to manage the hashset behavior but I think it is not a reliable solution.
I took the example of a basic deck card but each card is not only a "color", the number of fields, type of fields and methods of each class(Clubs,Diamonds,Spades,Hearts) differs.
This is a more specific definition of my class Card :
public abstract class Card
{
/**Keyword of this card*/
private final String keyword;
public Card(String keyword)
{
this.keyword = keyword;
}
public abstract void cardDefinition();
...
}
Here definition of my classes extending card :
public class Diamonds extends Card
{
/**KEYWORD of this card*/
public static final String KEYWORD = "cell";
/**Name of this cell*/
private final int id;
/**Universe of this cell*/
private final Universe universe;
/**Material name of this cell*/
private final String materialName;
public Diamonds(int id, Universe universe, String materialName)
{
super(KEYWORD);
this.id = id;
this.universe = universe;
this.materialName = materialName;
...
}
@Override
public void cardDefinition(){...}
public void someMethod(OrientedSurface orientedSurface) {...}
...
}
public class Spades extends Card
{
/**keyword of this card*/
public static final String KEYWORD = "mat";
/**Name of this material card*/
private final String name;
/**Density of this material card*/
private final double density;'
public Spades(String name, double density)
{
super(KEYWORD);
this.name = name;
this.density = density;
...
}
@Override
public void cardDefinition(){...}
public void someMethodBis(Material material) {...}
...
}
...
Upvotes: 0
Views: 55
Reputation: 7956
Based on your updated answer, perhaps using a mapping of keywords to Card
s might work for you:
Map<String, Card> cards = new HashMap<>();
This is assuming that keywords are unique, and that only one card per keyword should be in the map. Storing data in the map could then look like this:
Card mySpade = new Spade(...);
if (!cards.contains(Spades.KEYWORD)) {
cards.put(Spades.KEYWORD, mySpade);
}...
Upvotes: 1
Reputation: 140553
The HashSet
implementation uses the equals()
respectively hashCode()
methods of the objects you insert.
In other words: if you want to make that any Spade
is equal to any other Spade
object - you will have to @Override equals()
and hashCode()
accordingly.
Of course - that is a rather wrong design in the first place.
The suits should not be classes but enums. And then you use an EnumSet.
In other words, you rather go for:
public enum Suit { DIAMONDS, SPADE, ...
plus
public enum Value { TWO, THREE, ... JOKER ... whatever
to then have
public class Card {
private final Suit suit;
private finale Value value;
Meaning: you use enums to create a type that enumerates such kinds of values. And then your card objects simply get assigned Suit, Value, ... and so on. And by using enum and EnumSet you basically get the thing you are asking for ... for free.
Finally: good OOP is more than just putting extends
here or there. Your classes model reality. A suit is not a card! The suit is a property of a card.
Upvotes: 1
Reputation: 5843
Write a dedicated class for the job, which internally uses a set. This class offers a public
method to add a new card, and before really adding the card to the set it checks if it is allowed. From outside you don't have access to the private
field containing the set, so you have to use the method that enforces the check.
Upvotes: 0