Classes: From Use to Implementation Anatomy of the Dice class ● The class Dice, need #include " dice.h " ● We’ve used several classes, a class is a collection of objects sharing similar characteristics ➤ Objects: six-sided dice, 32-sided dice, one-sided dice ➤ A class is a type in C++, like int , bool , double ➤ Methods: Roll(), NumSides(), NumRolls() ➤ A class encapsulates state and behavior ➤ A class is an object factory ● A Dice object has state and behavior ● string (this is a standard class), need #include <string> ➤ Each object has its own state, just like each int has its own ➤ Objects: " hello " , " there are no frogs " , … value ➤ Methods: substr(…), length(…), find(…), << • Number of times rolled, number of sides ➤ All objects in a class share method implementations, but ● Date need #include " date.h " access their own state • How to respond to NumRolls()? Return my own # rolls ➤ Objects: December 7, 1949, November 22, 1963 ➤ Methods: MonthName(), DaysIn(), operator - A Computer Science Tapestry 6.1 A Computer Science Tapestry 6.2 The header file dice.h The header file is a class declaration class Dice ● What the class looks like, but now how it does anything { ● Private data are called instance variables public: Dice(int sides); // constructor ➤ Sometimes called data members, each object has its own int Roll(); // return the random roll ● Public functions are called methods , member functions , these int NumSides() const; // how many sides are called by client programs int NumRolls() const; // # times this die rolled private: ● The header file is an interface, not an implementation int myRollCount; // # times die rolled ➤ Description of behavior, analogy to stereo system int mySides; // # sides on die ➤ Square root button, how does it calculate? Do you care? }; ● The compiler reads this header file to know what’s in a Dice ● Information hiding and encapsulation, two key ideas in object designing programs, object-oriented or otherwise ● Each Dice object has its own mySides and myRollCount A Computer Science Tapestry 6.3 A Computer Science Tapestry 6.4
From interface to use, the class Dice Header file as Interface #include “dice.h” ● Provides information to compiler and to programmers Objects constructed int main() cube.myRollCount == 0 ➤ Compiler determines how big an object (e.g., Dice cube(6)) { cube.mySides == 6 is in memory Dice cube(6); dodeca.myRollCount == 0 ➤ Compiler determines what methods/member functions can Dice dodeca(12); dodeca.mySides == 12 be called for a class/object int x = cube.Roll(); ➤ Programmer reads header file (in theory) to determine int k; Method invoked what methods are available, how to use them, other for(k=0; k < 6; k++) cube.myRollCount == 1 information about the class { x = dodeca.Roll(); cube.mySides == 6 } ● What about CD, DVD, stereo components? return 0; ➤ You can use these without knowing how they really work After for loop } ➤ Well-designed and standard interface makes it possible to dodeca.myRollCount == 6 connect different components dodeca.mySides == 12 ➤ OO software strives to emulate this concept A Computer Science Tapestry 6.5 A Computer Science Tapestry 6.6 William H. (Bill) Gates, ( b. 1955 ) From Interface to Implementation CEO of Microsoft, richest ● The header file provides compiler and programmer with how ● to use a class, but no information about how the class is person in the world (1999) implemented ➤ First developed a BASIC compiler while at Harvard ➤ Important separation of concerns, use without complete understanding of implementation ➤ Dropped out (asked to leave?) went on to develop ➤ Implementation can change and client programs won’t Microsoft (hopefully) need to be rewritten “ You’ve got to be willing to read • If private section changes, client programs will need to recompile other people’s code, then write your own, then have other • If private section doesn’t change, but implementation does, then client programs relinked, but not recompiled people review your code ” Generous to Computer Science ● ● The implementation of foo.h is typically in foo.cpp, this is a and philanthropic in general convention, not a rule, but it’s well established (foo.cc used ● Visionary, perhaps cutthroat too) A Computer Science Tapestry 6.7 A Computer Science Tapestry 6.8
Implementation, the .cpp file More on method implementation ● In the implementation file we see all member functions written, ● Each method can access private data members of an object, so same idea as functions we’ve seen so far same method implementation shared by different objects ➤ cube.NumSides() compared to dodeca.NumSides() ➤ Each function has name, parameter list, and return type ➤ A member function’s name includes its class ➤ A constructor is a special member function for initializing an int Dice::NumSides() const // postcondition: return # of sides of die object, constructors have no return type { return mySides; Dice::Dice(int sides) } // postcondition: all private fields initialized { int Dice::Roll() myRollCount = 0; // postcondition: number of rolls updated mySides = sides; // random ’die’ roll returned } { RandGen gen; // random number generator (“randgen.h”) int Dice::NumSides() const // postcondition: return # of sides of die myRollCount= myRollCount + 1; // update # of rolls { return gen.RandInt(1,mySides); // in range [1..mySides] return mySides; } } A Computer Science Tapestry 6.9 A Computer Science Tapestry 6.10 Understanding Class Implementations Class Implementation Heuristics ● You do NOT need to understand implementations to write ● All data should be private programs that use classes ➤ Provide accessor functions as needed, although classes ➤ You need to understand interfaces, not implementations should have more behavior than simple GetXXX methods ➤ However, at some point you’ll write your own classes ● Make accessor functions const ➤ Easy to use const functions (we’ll see more on const ● Data members are global or accessible to each class method later), although difficult at times to implement properly ● Constructors should assign values to each instance variable ➤ A const function doesn’t modify the state of an object int Dice::NumSides() const ● Methods can be broadly categorized as accessors or mutators // postcondition: return # of sides of die ➤ Accessor methods return information about an object { • Dice::NumRolls() and Dice::NumSides() return mySides; ➤ Mutator methods change the state of an object } • Dice::Roll(), since it changes an object’s myNumRolls A Computer Science Tapestry 6.11 A Computer Science Tapestry 6.12
Building Programs and Classes Design Heuristics ● To develop a program, written with classes or not, start small ● Make each function or class you write as single-purpose as possible ➤ Get a core working, and add to the core ➤ Avoid functions that do more than one thing, such as ➤ Keep the program working, easier to find errors when reading numbers and calculating an average, standard you’ve only a small amount of new functionality deviation, maximal number, etc., ➤ Grow a program incrementally rather than building a • If source of numbers changes how do we do statistics? program all at once • If we want only the average, what do we do? ➤ Classes should embody one concept, not several. The ● Start with a prototype behavior/methods should be closely related ➤ Incomplete, but reasonable facsimile to the final project ➤ Help debug design, ideas, code, … ● This heuristic is called Cohesion , we want functions and ➤ Get feedback to stay on track in developing program classes to be cohesive, doing one thing rather than several • From users, from compiler, from friends, from yourself ➤ Easier to re-use in multiple contexts A Computer Science Tapestry 6.13 A Computer Science Tapestry 6.14 Design Heuristics continued Reference parameters ● It’s useful for a function to return more than one value ● Functions and classes must interact to be useful ➤ Find roots of a quadratic ➤ One function calls another ➤ One class uses another, e.g., as the Dice::Roll() ➤ Get first and last name of a user function uses the class RandGen ● Functions are limited to one return value ➤ Combine multiple return values in object (create a class) ➤ Use reference parameters to send values back from ● Keep interactions minimal so that classes and functions don’t function rely too heavily on each other, we want to be able to change • Values not literally returned one class or function (to make it more efficient, for example) • Function call sends in an object that is changed without changing all the code that uses it ● Sometimes caller wants to supply the object that’s changed ● Some coupling is necessary for functions/classes to string s = ToLower("HEllO") // return type? communicate, but keep coupling loose string s = "HeLLo"; ToLower(s); // return type? ➤ Change class/function with minimal impact A Computer Science Tapestry 6.15 A Computer Science Tapestry 6.16
Recommend
More recommend