Classes and Objects |
A complete PDF version of the text book is now available. The PDF version is an almost complete subset of the HTML version (where only a few, long program listings have been removed). See here. |
This is the first chapter about classes. It is also the first chapter in the first lecture about classes. Our basic coverage of classes runs until Chapter 13.
|
10.1. The Die Class
Contents Up Previous Next Slide Annotated slide Aggregated slides Subject index Program index Exercise index
In this section we encounter a number of important OOP ideas, observations, and principles. We will very briefly preview many of these in a concrete way in the context of a simple initial class. Later we will discuss the ideas in depth.
We use the example of a die, which is the singular form of "dice", see Program 10.1. One of the teaching assistants in 2006 argued that the class Die is a sad beginning of the story about classes. Well, it is maybe right. I think, however, that the concept of a die is a good initial example. So we will go for it!
On purpose, we are concerned with use of either the singular or the plural forms of class names. The singular form is used when we wish to describe and program a single phenomenon/thing/object. The plural form is most often used for collections, to which we can add or delete (singular) objects. Notice that we can make multiple instances of a class, such as the Die class. In this way we can create a number of dice.
The class Die in Program 10.1 is programmed in C#. We program a die such that each given die has a fixed maximum number of eyes, determined by the constant maxNumberOfEyes. The class encapsulates the instance variables: numberOfEyes, randomNumberSupplier, and the constant maxNumberOfEyes. They are shown in line 4-6. The instance variable are intended to describe the state of a Die object, which is an instance of the Die class. The instance variable numberOfEyes is the most important variable. The variable randomNumberSupplier makes it possible for a Die to request a random number from a Random object.
After the instance variables comes a constructor. This is line 8-11. The purpose of the constructor is to initialize a newly create Die object. The constructor makes the random number supplier, which is an instance of the System.Random class. The constructor happens to initialize a normal six-eyed die. The expression DateTime.Now.Ticks returns a long integer, which we type cast to an int. The use of an unchecked context implies that we get an int out of the cast, even if the long value does not fit the range of int. (The use of unchecked eliminates overflow checking). The value assigned to numberOfEyes is achieved by tossing the die once via activation of the method NewTossHowManyEyes. The call of NewTossHowManyEyes on line 10 delivers a number between 1 and 6. In this way, the initial state - the number of eyes - of a new die is random.
Then follows three operations. In most object-oriented programming languages the operations are called methods. The Toss operation modifies the value of the numberOfEyes variable, hereby simulating the tossing of a die. The Toss operation makes use of a private method called NewTossHowManyEyes, which interacts with the random number supplier. The NumberOfEyes method just accesses the value of the instance variable numberOfEyes. The ToString method delivers a string, which for instance can by used if we decide "to print a Die object". The ToString method in class Die overrides a more general method of the same name.
We notice that the instance variables are private and that the constructors and methods are public. Private instance variables cannot be used/seen from other classes. This turns out to be important for us, see Section 11.4.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | using System; public class Die { private int numberOfEyes; private Random randomNumberSupplier; private const int maxNumberOfEyes = 6; public Die(){ randomNumberSupplier = new Random(unchecked((int)DateTime.Now.Ticks)); numberOfEyes = NewTossHowManyEyes(); } public void Toss(){ numberOfEyes = NewTossHowManyEyes(); } private int NewTossHowManyEyes (){ return randomNumberSupplier.Next(1,maxNumberOfEyes + 1); } public int NumberOfEyes() { return numberOfEyes; } public override String ToString(){ return String.Format("[{0}]", numberOfEyes); } } | |||
|
Below, in Program 10.2 we see a client of class Die, which creates and repeatedly tosses three dice. A client of a Die uses a die via a number of Die references. In Program 10.2 d1, d2, and d3 are references to Die objects. Section 10.2 is about clients and servers.
When we run the program we get the output shown in Listing 10.3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | using System; class diceApp { public static void Main(){ Die d1 = new Die(), d2 = new Die(), d3 = new Die(); for(int i = 1; i < 10; i++){ Console.WriteLine("Die 1: {0}", d1); // Implicitly Console.WriteLine("Die 2: {0}", d2); // calls Console.WriteLine("Die 3: {0}", d3); // ToString in Die d1.Toss(); d2.Toss(); d3.Toss(); } } } | |||
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | Die 1: [1] Die 2: [1] Die 3: [1] Die 1: [2] Die 2: [2] Die 3: [2] Die 1: [3] Die 2: [3] Die 3: [3] Die 1: [4] Die 2: [4] Die 3: [4] Die 1: [3] Die 2: [3] Die 3: [3] Die 1: [2] Die 2: [2] Die 3: [2] Die 1: [3] Die 2: [3] Die 3: [3] Die 1: [2] Die 2: [2] Die 3: [2] Die 1: [1] Die 2: [1] Die 3: [1] | |||
|
The output shown in Program 10.1 seems suspect. Why? Take a close look. We will come back to this problem in Exercise 3.7, which we encounter in Section 11.10. (At that location in the material we have learned enough to come up with a good solution to the problem).
The Die class is a template or blueprint from which we can create an arbitrary number of die objects |
The term blueprint is often used as a metaphor of a class (seen in relation to objects). The word 'blueprint' is, for instance, used for an architect's drawing of a house. In general, a blueprint refers to a detailed plan for something that, eventually, is going to be constructed. The blueprint can be used as a prescription from which craftsmen can actually built a house.
The class Die from Program 10.1 is only useful if we apply it in some context where dice are actually needed. We use dice in various games. In Exercise 3.1 we propose that you make a simple Yahtzee game, with use of five dice (five instances of the Die class).
Exercise 3.1. Yahtzee Write a very simple Yahtzee program based on the Die class. Yahtzee is played by use of five dice that are tossed simultaneously. The players are supposed to fill out a table of results. The table should allow registration of ones, ..., sixes, three-of-a-kind, four-of-a-kind, full-house, small-straight, large-straight, yahtzee, and chance. See wikipedia for more details and inspiration. Be sure to use the version of the Die class that shares the Random class with the other dice. This version of the Die class is produced in another exercise in this lecture. This program is for a single player, who tosses the five dice repeatedly. Each time the five dice are tossed a table cell is filled. No re-tossing is done with less than five dice. The first category that fits a given toss is filled. (Try yahtzee first, Chance last). Keep it simple! You may consider to write a YahtzeeTable class which represents the single user table used to register the state of the game. Consider the interface and operations of this class. There is no solution to this exercise |
10.2. Clients and Servers
Contents Up Previous Next Slide Annotated slide Aggregated slides Subject index Program index Exercise index
The names client and server is often used when we are concerned with computers. A server denominate a computer that provides services to its surrounding. It could be a file server or a web server.
In the context of object-oriented programming the words client and server will be used as object roles. In a given situation an object plays a given role. An object x is called a client of y if x makes use of the services (operations) provided by y. An object y is called a server of x if it provides services (operations) to x.
In a dice game the objects act, in turn, as client and servers. |
Figure 10.1 Interacting Game, Die, and Random objects. The Game object is a client of the Die objects, which in turn are clients of the Random objects. |
Figure 10.1 shows a single game object, three die objects, and three random objects. The client-server roles of these objects can be summarized as follows:
|
In the figure, the arrows are oriented from clients to servers.
10.3. Message Passing
Contents Up Previous Next Slide Annotated slide Aggregated slides Subject index Program index Exercise index
A client interacts with its connected servers via message passing.
As a metaphor, we pretend that objects communicate by means of message passing |
Message passing actually covers a procedure call. Procedure calling is a technical matter. Message passing is an everyday term that covers some communication between one person and another, for instance via postal mail. In some setups, message passing also involves the receiving of a reply. As already stressed earlier, use of metaphors is very important for getting new ideas, and for raising the level of abstraction.
In Figure 10.2 we illustrate message passing in between a game object, three dice, and three random objects.
Figure 10.2 Interacting Game, Die, and Random objects |
In some versions of this teaching material you will be able to animate the figure, such that you can actually see the acts of passing a message and receiving a reply. Before sending a message, the sending object is emphasized. When emphasized, we say that the object is the current object. In a single threaded program execution, there is always a single current object. This is the object, which most recently received a message. In football, message passing corresponds to passing the ball from player to player. At some level of abstraction, there is always a single player - 'the ball keeper' - who posses the ball. He or she corresponds to the current object.
Here follows some general remarks about message passing.
|
In the next chapter we will dive into the details of the class concept.