750 likes | 844 Views
ReviewSlides. CMPS 2143. CHAPTER 11. Advantages/Disadvantages. Statically typed languages Type checking can be done at compile time Memory layout can be determined at compile time for automatic variables EFFICIENT Dynamically typed languages FLEXIBILITY Example: .
E N D
ReviewSlides CMPS 2143
Advantages/Disadvantages • Statically typed languages • Type checking can be done at compile time • Memory layout can be determined at compile time for automatic variables • EFFICIENT • Dynamically typed languages • FLEXIBILITY • Example: function max (left, right) { if (left < right) return right; return left; }
Static versus Dynamic Method Binding • In OOP languages, the binding of a method to execute in response to a message is determined by the dynamic value of the receiver.
C++ class Animal { public: virtual void speak() {cout << “Animal Speak !”;} }; class Dog : Animal { public: virtual void speak() {cout << “Woof !”;} }; Animal pet; //automatic memory allocation!!! Dog d; d.speak(); //Woof ! pet = d; pet.speak(); //Animal Speak !
C++ class Animal { public: virtual void speak() {cout << “Animal Speak !”;} }; class Dog : Animal { public: virtualvoid speak() {cout << “Woof !”;} }; Animal * pet; //dynamic memory allocation!!! Dog * d = new Dog(); D->speak(); //Woof ! pet = d; pet->speak(); //Woof!
Space Allocation • Minimum space allocation: Allocate the amount of space necessary for the base class. • Maximum space allocation: Allocate the amount of space necessary to hold the maximum size of any legal value (from any of the classes in the hierarchy) • Dynamic memory allocation: Allocate only the amount of space necessary to hold a single pointer/reference. (Allocate the space necessary for the value at runtime on the heap.)
Minimum Space Allocation • Default: not all fields copied/only the corresponding fields. (termed slicing)
Dynamic Memory Allocation • Values of objects not stored on the stack – only the pointer or reference is • Values stored in the heap. • Java, Smalltalk, Object Pascal, Objective-C use this approach • Must use new to allocate space in the heap.
Assignment – 2 interpretations • Copy semantics – assignment copies entire value of right side, assigning it to left, thereafter the two values are independent (changes in one not reflected in other) • Sometimes used in C++, sometimes not • Pointer semantics – Assignment changes the reference of left side to be of right side (aliasing). Two pointers refer to the same memory location. (Changes in one, will affect the other.) • Java, CLOS, Object Pascal • If used, languages usually provide a means for true copy
Copies and Clones • How to copy a value that references other objects? • Shallow copy • assignment of references • Deep copy • Overload assignment • Write copy constructor • Overload clone method
Multiple Inheritance of Interfaces • C++ and Smalltalk allow multiple inheritance of classes • Java and C# do not • Fake it with multiple inheritance of interfaces • REUSE concept, not code!
Four forms of polymorphism • Overloading – ad hoc polymorphism • Overriding – inclusion polymorphism • Polymorphic variables – assignment polymorphism • or if used as an argument to a method/function – pure polymorphism • Generics (templates) • Downcasting – reverse polymorphism
Overloading • AKA ad-hoc polymorphism • Single function/method name has several alternative implementations • Distinguished at compile time by type signature class myClass { public: //3 overloaded meanings for same name void example (int x) {…} void example (int x, double y) {…} void example (string x) {…} }
Overriding • Single function/method name has several alternative implementations with the same signature, but occurs within context of the parent class/child class relationship class Parent { public: void example (int x) {…} } class Child { public: //same name, different method body void example (int x) {…} }
Polymorphic Variable • also known as assignment polymorphism • Variable is declared of one type, but holds a value of a different type //declared as parent, holding child value Room r = new King(…); • When a polymorphic variable is used as an argument, the result function/method is said to exhibit pure polymorphism.
Generics/Templates – More in Chapter 18 • A way of creating general purpose tools and specializing them to specific situations template <class T> T max (T left, T right){ if (left < right) return right; return left; } • A generic function or class is parameterized by type • Similar to the way a function is parameterized by values • The type is unspecified, to be filled in later
OPERATOR OVERLOADING • Some languages allow operator overloading • Java does not • Giving the normal C++ operators such as +, -, * , <=, and += etc. , additional meanings when they are applied to user-defined types (classes) • You cannot create new operators like *& and try to overload them; only existing operators can be overloaded
OVERLOADING BINARY OPERATORS class StringExt : public Object { public: //constructors StringExt(); StringExt(string s); StringExt(constStringExt & other); //overloaded + for concatenation StringExtoperator + (StringExt se); StringExtoperator + (int i); StringExtoperator + (double r); StringExtoperator + (string s); //overloaded = for assignment void operator = (string s); void operator = (StringExt se); //returns the string equivalent of the StringExt virtual string toString (); private: string val; };
Resolving Overloaded Calls Example: void order (Dessert d, Cake c); void order (Pie p, Dessert d); void order (ApplePie a, Cake c); order (aDessert, aCake); //legal;exact- 1 order (anApplePie, aDessert); //legal - 2 order (aDessert, aDessert); //illegal //all eliminated in step 1, can’t downcast order (anApplePie, aChocolateCake); //legal //all in set; 1,2 eliminated in step2, //because 3’s parameters more specific order (aPie, aCake); //illegal //3 elim. in step 1, but 2 and 3 survive step 2
Conversion • C++ gives programmer control over how an instance of a class can be implicitly converted to another type • use a constructor with a single argument • rule to compiler to convert arg type to class type class ComplexNumber { public: ComplexNumber(); ComplexNumber(double r, double i); ComplexNumber (double r); : } ComplexNumber::ComplexNumber (double r) { real = r; imag = 0; }
ComplexNumber c(4.5,3.2); ComplexNumber result; double r = 5; result = c + r; //r will be converted to a //ComplexNumber and ComplexNumber + //will be performed
Overriding • Recall, a method in a child class overrides a method in the parent class, if it has the same name and type signature. • Also known as inclusion polymorphism • important when combined with substitution Parent void method (int, float Child AnotherChild void method (int, float …
Overriding vs Overloading Overloading Overriding • same method name • two or more method bodies • classes that methods appear in do NOT have to be in parent/child relationship • signatures MUST NOT match • methods are SEPARATE • resolved at COMPILE-TIME • same method name • two or more method bodies • classes that methods appear in MUST be in parent/child relationship • signatures MUST match • methods SOMETIMES COMBINED • resolved at RUN-TIME
Replacement vs Refinement • There are actually two different ways that overriding can be handled: • A replacement totally and completely replaces the code in the parent class the code in the child class. • A refinement executes the code in the parent class, and adds to it the code in the child class. • Constructors, for example, almost always use refinement.
Replacement • Two major reasons for using replacement • the method is the parent class is abstract (or pure virtual), it MUST be replaced • the method in the parent class is a default method, not appropriate for all situations • recall Animal speak() method, and Dog speak method() earlier • the child method is more efficient than the parent method • parent class polygon and child class square with methods computeArea();
Refinement • Code in child class combined with code in parent class and both executed • constructors perform a refinement • in most languages, code from parent class executed first
Refinement • C++ example void Parent:: example(int a) { cout << “in parent code\n”; } void Child::example(int a) { Parent::example(12); //do parent action cout << “in child code\n”; } • Java example class Parent { public void example(int a) {cout<< “in parent code\n”;} } class Child { public void example(int a) { super.example(12); //do parent action cout<< “in child code\n”; }
Overriding versus Shadowing • It is common in programming languages for one declaration of a variable to shadow a previous variable of the same name • Shadowing is resolved at compile time class Silly { private int x; // an instance variable named x public void example (int x) { // x shadows instance variable int a = x+1; while (a > 3) { int x = 1; //local variable shadows parameter a = a - x; } } }
Shadowing Methods • Many of those languages that require the virtual keyword in the parent class will use shadowing if it is omitted: class Parent { public: // note, no virtual keyword here void example () { cout << "Parent" << endl; } }; class Child : public Parent { public: void example () { cout << "Child" << endl; } }; Parent * p = new Parent(); p->example(); //Parent Child * c = new Child(); c->example(); //Child p = c; // be careful here! p->example(); // Parent
Overriding, Shadowing and Redefinition • Overriding • The type signatures are the same in both parent and child classes, and the method is declared as virtual in the parent class. • Shadowing • The type signatures are the same in both parent and child classes, but the method was not declared as virtual in the parent class. • Redefinition • The type signature in the child class differs from that given in the parent class. • (Example available in Chapter 15)
The Polymorphic Variable • A polymorphic variable is a variable that can reference more than one type of object (that is, it can hold values of different types during the course of execution). • Example public class Shape{ } public Shape shapes[ ]; public void drawAll(Shape [] shapes) { for (inti = 0; i < numShapes; i++) shapes[i].drawSelf(); } The variable was declared as Shape, but actually held a number of different types.
Downcast (Reverse Polymorpism) • It is sometimes necessary to undo the assignment to a polymorphic variable. • That is, to determine the variables true dynamic value, and assign it to a variable of the appropriate type. This process is termed down casting, or, since it is undoing the polymorphic assignment, reverse polymorphism.
Downcast (Reverse Polymorpism) • Examples in Java and C++: Parent aVariable = ...; Child aChild; if (aVariable instanceof Child) aChild = (Child) aVariable; Parent * aVariable = new ...; Child * aChild = dynamic_cast <Child *> (aVariable); if (aChild != 0) {//null if not legal, nonnull if ok . : }
Pure Polymorphism • A polymorphic method (also called pure polymorphism) occurs when a polymorphic variable is used as an argument. Different effects are formed by using different types of values. • Different objects implement toString differently, so the effects will vary depending upon the argument. class StringBuffer { String append (Object value) { return append(value.toString()); } ... }
Another form of polymorphism • Generics (or templates) in C++ provide a way to parameterize a function or a class by use of a type • A name is defined as a type parameter in the case of a class, eg. List <int> list; • Then that type is used within the class definition in place of the parameter • Generics in C++, Eiffel, ML, Haskell, Ada, and Java 7
The template class declaration template <class T> class NewClass { public: NewClass (); NewClass (T initialData); NewClass (NewClass other); void setData (const T & newValue); T getData () const; void resize (int newSize); NewClass operator + (constNewClass & newClass1, constNewClass & newClass2) private: T theData; }; #include “NewClass.cpp”
Methods template <class T> T NewClass::setData(const T & newValue) { theData = T; //assumes = is defined for T } template <class T> NewClass<T> NewClass <T>::operator + (constNewClass<T> & newClass1, constNewClass<T> & newClass2) { NewClass <T> result; result = ??? return result; }
Ex2. Instead non-member function looks like NewClassnmFunction(constNewClass & newClass1, constNewClass & newClass2) { . . . } template <class T> NewClass<T> nmFunction (constNewClass<T> & newClass1, constNewClass<T> & newClass2) { … }
NOTE: The name NewClass is changed to NewClass <T> only when it is used as a class name void main() { NewClass<int> myFirst; NewClass<int> mySecond(2); NewClass <int> myThird (33); NewClass <double> myFourth (4.5); myFirst.setData (5); cout << myFourth.getData() << endl; myFirst = nmFunction (mySecond, myThird); . :
Reusable containers • Simple data structures in almost all nontrivial programs • Examples: vectors, linked lists, stacks, queues, binary trees, sets, dictionaries, etc. • So common expect ideal for development as reusable components
inheritance as mechanism for specialization (Set and Bag) • deferred methods (add and remove in Collection) • inheritance as mechanism for construction (Dictionary)
composition (Bag has a dictionary) • key is the element in the bag • value is the number of times element is in the bag