Introduction to Object-oriented Programming |
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. |
|
Below we will return to the example of the Hangman game, which we studied as a structured program in Section 1.2.
4.1. An object-oriented program: Hangman
Contents Up Previous Next Slide Annotated slide Aggregated slides Subject index Program index Exercise index
In Figure 4.1 we show a class diagram of our object-oriented version of the Hangman game.
The class Puzzle encapsulates the data of a single puzzle (the category and the word phrase). The class also offers an interface through which these informations can be accessed.
The class PuzzleCollection represents a number of puzzles. It is connected to the file system (or a database) where we keep the collection of puzzles while not playing a game. How this 'persistency' is actually handled is ignored for now.
Similar observations can be done for HighscoreEntry and HighscoreList.
The class HangmanGame encapsulates the state of a single (round of the) hangman game. It has associations to a player and a secret puzzle, and to the collections of puzzles and highscore entries. We do not in HangmanGame want to commit ourselves to any particular user interface. Thus, the actual user interface of the game is not part of the HangmanGame class.
Figure 4.1 The classes of a Hangman program. At the left hand side we see that PuzzleCollection is formed by Puzzle parts. Similarly, the HighscoreList is formed by HighScoreEntry parts. The HangManGame class if formed by three parts: PuzzleCollection, HighScoreList, and Player. Both file system and user interface aspects are "cloudy" in this diagram. |
Below we show sketches of the individual classes in the game. The classes and all the operations are marked as abstract, because the operations of the classes are not implemented, and because the current OOP version of the Hangman game is written at a very high level of abstraction. The concatenation of all classes in Program 4.1 - Program 4.6 can actually be compiled with a C# compiler. Abstract classes are discussed in Chapter 30.
The operation interfaces of the classes are most probably not yet complete, but they are complete enough to let you have an impression of the object-oriented programming approach.
1 2 3 4 5 6 7 8 9 10 11 12 | abstract class Puzzle { public abstract string Category{ get; } public abstract string PuzzlePhrase{ get; } public abstract int NumberOfCharsToGuess(); } | |||
|
Given that Program 4.1 - Program 4.6 contain so many abstract operations we will touch a little bit on what this means. It is not intended that you should learn the details of abstract classes here, however. This is the topic of Section 30.1. As noticed above, the abstract class shown in Program 4.1 can actually be compiled with a C# compiler. But it is clear that the class cannot be instantiated (no objects can be made). It is necessary to create a subclass of Puzzle in which we give the details of the abstract operations (methods and properties). Subclassing and inheritance will be discussed in Chapter 25 and subsequent chapters. In the subclass of Puzzle we need to supply puzzle data representation details.
1 2 3 4 5 6 7 8 9 10 | abstract class HighScoreEntry { public abstract Player Player { get; } public abstract int Score{ get; } } | |||
|
Let us make a technical remark related to programming of abstract classes in C#. It is necessary to mark all operations (methods and properties) without bodies as 'abstract'. When a class contains at least one abstract operation, the class itself must also be marked as abstract. It is not sufficient to use the abstract modifier on the class.
1 2 3 4 5 6 7 | abstract class Player { public abstract string Name{ get; } } | |||
|
1 2 3 4 5 6 7 8 9 10 11 12 13 | abstract class PuzzleCollection { public abstract string Count{ get; } public abstract Puzzle this[int i]{ get; } public abstract void Add(Puzzle p); } | |||
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | abstract class HighScoreList { /* Invariant: Entries always sorted */ public abstract void Open(string FileName); public abstract string Count{ get; } public abstract HighScoreEntry this[int i]{ get; } public abstract void Add(HighScoreEntry e); public abstract void Close(); } | |||
|
The class HangmanGame in Program 4.6 (only on web) shows an outline of top-level class, cf. Figure 4.1. The operations in this class are intended to be called directly or indirectly by the Main method (not shown).
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 29 30 | public enum GameState {Ongoing, Won, Lost} abstract class HangmanGame { /* Encapsulates the data of a single play of Hangman */ /** Set the puzzle of this game */ public abstract void setPuzzle(Puzzle p); /** Get the secret puzzle of this game */ public abstract Puzzle CurrentPuzzle(); /** Set the alphabet of this game - a array of all possible chars */ public abstract void setAlphabet(char[] alphabet); /** Return the array of all chars not yet guessed */ public abstract char[] RemainingAlphabet(); /** Return a string which represents the guessing state */ public abstract string PuzzleOutline(Puzzle p); /** Call this method when the user wish to attempt ch */ public abstract void GuessChar(char ch); /** Return the state of the game - Won, Lost or Ongoing */ public abstract GameState GameState(); /** Return the number of points obtained until now in this game */ public abstract int HowManyPoints(); } | |||
|