DEVTOME.COM HOSTING COSTS HAVE BEGUN TO EXCEED 115$ MONTHLY. THE ADMINISTRATION IS NO LONGER ABLE TO HANDLE THE COST WITHOUT ASSISTANCE DUE TO THE RISING COST. THIS HAS BEEN OCCURRING FOR ALMOST A YEAR, BUT WE HAVE BEEN HANDLING IT FROM OUR OWN POCKETS. HOWEVER, WITH LITERALLY NO DONATIONS FOR THE PAST 2+ YEARS IT HAS DEPLETED THE BUDGET IN SHORT ORDER WITH THE INCREASE IN ACTIVITY ON THE SITE IN THE PAST 6 MONTHS. OUR CPU USAGE HAS BECOME TOO HIGH TO REMAIN ON A REASONABLE COSTING PLAN THAT WE COULD MAINTAIN. IF YOU WOULD LIKE TO SUPPORT THE DEVTOME PROJECT AND KEEP THE SITE UP/ALIVE PLEASE DONATE (EVEN IF ITS A SATOSHI) TO OUR DEVCOIN 1M4PCuMXvpWX6LHPkBEf3LJ2z1boZv4EQa OR OUR BTC WALLET 16eqEcqfw4zHUh2znvMcmRzGVwCn7CJLxR TO ALLOW US TO AFFORD THE HOSTING.

THE DEVCOIN AND DEVTOME PROJECTS ARE BOTH VERY IMPORTANT TO THE COMMUNITY. PLEASE CONTRIBUTE TO ITS FURTHER SUCCESS FOR ANOTHER 5 OR MORE YEARS!

Enumerated Types

If you look back at the first chapter on Classes we had to deal with an issue:

 public void setNameValue(String cardName){
	name = cardName; - sets the name
	switch(value) {
	case “Ace”: 	value = 1;
		break;
	case “Two”:	value = 2;
				break;
		- others skipped to make it shorter
		case “King”:	value = 10;
				break;
		default:	value = -1; - An error value
				name = “error”; 
				break;
		}
	}

If the string cardName doesn’t match an expected value, we have to set it to some error value. This is a bit annoying – and we’d prefer not to deal with it.

It’s always better to stop incorrect data being entered in the first place than to check it afterwards.

(This isn’t only true in programming – for example, consider websites where you have to enter data. Drop-down lists which only let you choose the legal values are more convenient than text boxes where you could type anything which could well be wrong.)

Enumerated Types

What we want is some way of listing only the allowed values. Many programming languages have the concept of an enumerated type, including Java. An enumerated type lists, or enumerates, the permitted values. We’ve already seen a sort-of example of this – the boolean type just consists of two values. Enumerated types aren’t suitable for everything – there need to be few enough values that you can reasonable list them all in a program (so a few tens at most). Enumerated types have a very simple, basic, syntax in Java:  

public enum CitrusFruit {
	LEMON, ORANGE, LIME, GRAPEFRUIT, KUMQUAT
}

(We said ‘basic’ syntax because we can do more complicated things and will do later on.)

We can use them quite simply:

CitrusFruit someFruit;
someFruit = CitrusFruit.LEMON; // sets someFruit to LEMON

The only values a CitrusFruit variable can take are those listed in the definition of the type.

(Hopefully you can see now how this relates to cards – suites only have four possible values; and cards only 13 – well within the sensible sizes of possible values that make sense for an enumerated type.)

Enumerated Types in the Card Classes

Based on the example above, we can do something like this:

public enum Suite {
	- This a *new type* with only these values allowed
	CLUBS, DIAMONDS, HEARTS, SPADES	
}

and it also looks as if we can do the same for the names – and we can, but we can also do a bit more than that. Recall that the name and value of a card are linked: once you know the name, you can work out the value. Can we include that somehow? Yes we can – but first we need to look at what enumerated types in Java really are.

Enumerated Types are Classes

Enumerated types are just a kind of renamed class – what’s actually happening, internally, hidden from us, is:

public class Suite {
	public static CLUBS = new Suite();
	public static DIAMONDS = new Suite();
	public static HEARTS = new Suite();
	public static SPADES = new Suite();

	private Suite() {
	}
}

We have created a normal class but unlike our usual approach where the variables are private and the methods and constructors are public (or at least some of them), here we have public variables and a private constructor. This means: • The values of CLUBS, DIAMONDS etc. are visible outside the class (which we need to happen so we can use them). • There can never be anymore Suite items than those we create inside Suite – because the constructor is private we can only call it from inside Suite, and we only do that four times.

Enumerated Types that Do More

So, if enumerated types are really classes, can we treat them like classes and add more functions? Yes – here’s an enumerated type that handles names and values:

public enum CardName {
	ACE(1),		-  These enum items are also 
	TWO(2),		-  constructor calls
	THREE(3),		-  to the constructor CardName below
	FOUR(4),
	FIVE(5),
	SIX(6),
	SEVEN(7),
	EIGHT(8),
	NINE(9),
	TEN(10),
	JACK(10),
	QUEEN(10),
	KING(10);
	
	private final int value;
	
	//  As well as creating the CardName Objects
	//  ACE ... KING, they also add a *value*
	//  to each one
	CardName(int cardValue){
		value = cardValue;
	}
	
	public int value() {
		return value;
	}
}

This time when we list the elements of the enumerated type, we pass an integer as a parameter. We’ve also explicitly written out the constructor for it, which saves that integer in a variable. We also add a method to return the value of that integer. (Note this time we’ve listed all the enumerated type values one per line, and before we didn’t – there’s no real ‘rule’ about this, provided it’s readable.)

Having defined two enumerated types, we can now use them to redefine our Card class:

public class Card {
	
	private final Suite suite;
	private final CardName name;
	
	public Card(Suite suiteVal, CardName cardVal){
name = cardVal;
		suite = suiteVal;
	}
	
	public Suite getSuite() {
		return suite;
	}
	
	public CardName getName() {
		return name;
	}
	
	public int getValue() {
		return name.value();
	}
	
	public String toString() {
		return (name + " of " + suite);
	}
}

• Now we don’t pass in Strings as parameters, but variables of our two enumerated types. • We don’t do any error handling because only valid values are possible. • We don’t need to check the name to set the value, because that’s already done inside the CardName enumerated type. • Finally, we don’t need to separately store the value, because we can just call the value() method of the CardName enumerated type. This is much simpler and avoids many possible errors – or, more strictly, the errors will be spotted by the compiler and not reach the stage where code which is run will be executed.

Comparing Cards

One thing we cannot do yet but which is key to most uses of cards is to be able to compare and sort them. This is obviously important but it’s going to take a few tricky steps to manage.

How Do We Compare Cards?

This is the first decision we need to take – it’s pretty obvious that a Ten is higher than a Three – but is a Three of Clubs higher than a Three of Hearts? We haven’t considered the order of the suites at all. (There’s the other problem that different games use different values for cards – but we’re going to assume an Ace is the lowest and all picture cards - Jack, Queen, King - and Ten all have the same value.) To work out the sorting of the suites we first note that – traditionally – the order (from high to low) is: Spades, Hearts, Diamonds, Clubs. We’ve already said that we get a ‘free’ values() method when we defined the Suite enumerated type. So we could just make sure we define the suites in the right order (lowest to highest) and we’ll get an ordering automatically. But we don’t like leaving things like this implicit (i.e. not expressly written down) so we prefer to spell it out:

public enum SuiteCompare {
	SPADES(4), HEARTS(3), DIAMONDS(2), CLUBS(1);	
	
	private final int value;
	
	SuiteCompare(int suiteValue){
		value = suiteValue;
	}
	
	public int value() {
		return value;
	}

}

This now explicitly spells out what the relative numerical values of the suites are – we now just need to think of a way of using it.

The compareTo() Method

While it would be great to come up with some way of just using the > and < operators (as well as ==, !=, ⇐, >=) to compare cards, we can’t: the best we can do is come up with a method that works in a similar way to the equals() method we use for strings. We are going to write a method compareTo() that returns 0, 1, or -1 depending if two cards are equal, less than or greater than each other. This may seem an odd choice but bear with me – it will make sense. To do this, we’re going to define a new class called CardCompare that has our new method and uses our new enumerated type for suites – here’s the code:

public class CardCompare implements
				Comparable<CardCompare> {
	
	private final SuiteCompare suite;
	private final CardName name;
	
	public CardCompare(SuiteCompare suiteVal,
CardName cardVal){
name = cardVal;
		suite = suiteVal;
	}
	
	public SuiteCompare getSuite() {
		return suite;
	}
	
	public CardName getName() {
		return name;
	}
	
	
 
public int getValue() {
		return name.value();
	}
	
	public int getSuiteValue() {
		return suite.value();
	}
	
	public String toString() {
		return (name + " of " + suite);
	}
	
	public int compareTo(CardCompare card) {
		
		if(card.getValue() < name.value()) {
			return 1;
		} else if (card.getValue() > name.value()) {
			return -1;
		} else if (card.getSuiteValue() <
 suite.value()) {
			return 1;
		} else if (card.getSuiteValue() >
 suite.value()) {
			return -1;
		} else {
			return 0;
		}
	}
}

The compareTo() method first checks the card values; and if one is greater than the other uses that. Next, if the values are equal, it uses the suites to compare values. Only if the cards are equal (both value and suite) does it return zero

Sorting

The reason why we specifically wrote a method called compareTo() which does what it does is at the very top of the class:

public class CardCompare implements Comparable<CardCompare>

We haven’t seen this before. The keyword implements says that our class CardCompare contains implementations of the methods listed in a Java Interface – in this case the interface Comparable. I’m not going to explain how to write an interface (that’s for a later on) – but it’s basically just a list of the first lines of each method: the lines that say what the method name is, the arguments and the return type. Essentially Comparable in this case contains a line like this:

public int compareTo(CardCompare card);

So nothing about how the method works at all. By saying

public class CardCompare implements Comparable<CardCompare>

we are saying that our class CardCompare contains an implementation of this interface (which of course it does). This is important because there’s a method called Collections.sort(). This method will sort into order any class that implements the Comparable interface – it works because it knows that any class that does this must have the compareTo() method, which defines what ‘in order’ means for that particular class. In our case, compareTo() defines what it means for two cards to be ‘in order’. So we can use this Collections.sort() method (which, by the way, is written to be very efficient – you will see what this means later on) to put our cards back into sorted order without having to actually write code to do it. This is one of the great strengths of Object Oriented programming – the ability to reuse code like this so generally.

Computer Science


QR Code
QR Code enumerated_types_java (generated for current page)
 

Advertise with Anonymous Ads