250 likes | 261 Views
Explore the advanced topics of object-oriented programming, including dynamic inheritance, contract programming, and multiple dispatch. Learn about encapsulation, inheritance, and subtype polymorphism. Understand the role of classes and their various purposes in modern programming languages.
E N D
Object-Oriented Programming “The Rest of the Story”, CS 4450 – Chapter 16
Topics • What is OOP? • Objects Without Classes • “Dynamic inheritance” in Javascript, Python • Contract Programming • Multiple Dispatch
What is Object Oriented Programming? • Encapsulation • Inheritance • Subtype Polymorphism • or “equivalent”
Encapsulation • Separating interface from implementation • Different mechanisms • Classes & Interfaces • Nested functions and closures
The Role of Classes • Most OO languages have some kind of class construct • Classes serve a variety of purposes, depending on the language: • Group fields and methods together • Are instantiable: the running program can create as many objects of a class as it needs • Serve as the unit of inheritance: derived class inherits from base class or classes Modern Programming Languages
Classes • More purposes: • Serve as a type: objects (or references to them) can have a class or superclass name as their static type • House static fields and methods: one per class, not one per instance • Serve as a labeled namespace (scope); control the visibility of contents outside the class definition Modern Programming Languages
Without Classes • Imagine an OO language with no classes • With classes, you create objects by instantiating a class • Without classes, you could create an object from scratch by listing all its methods and fields on the spot • Or, you could clone an existing prototype object and then modify parts of it Modern Programming Languages
With classes: instantiation x = new Stack(); x = { private Node top = null; public boolean hasMore() { return (top!=null); } public String remove() { Node n = top; top = n.getLink(); return n.getData(); } …} y = x.clone();y.top = null; Without classes: raw object creation Without classes: prototype cloning Modern Programming Languages
Prototypes • A prototype is an object that is copied to make similar objects • When making copies, a program can modify the values of fields, and can add or remove fields and methods (“dynamic OOP”) • Prototype-based languages (Self, Javascript to some degree) use this concept instead of classes Modern Programming Languages
Without Classes • Instantiation is only one use of classes • Other things prototype-based languages must do without: • Classes as types: most prototype-based languages are dynamically typed • Inheritance: “static inheritance” requires classes • Prototype languages use “dynamic inheritance” • aka “delegation” Modern Programming Languages
Inheritance • Inheritance is a way to defer attribute or method selection to another type • a “superclass” • This is static inheritance • since relationships among types are defined in source code • There is another way…
Delegation“Runtime Inheritance” • Object (not type)-based inheritance • Instead of a superclass, an object has a delegate • aka “prototype” (just another object) • Delegates are set at runtime • Any unresolved name lookup defers to the delegate object • and so on up the delegate chain… • A similar effect to subtype polymorphism, but without types! • See prototype.ds (Javascript), prototype.py
About Dynamic Typing • An object may or may not be able to respond to a particular request (“message”) — no compile-time check • Total freedom: program can try using any method for any object • Polymorphism isa “given” in dynamically-typed languages • Polymorphism is only a conscious concern in statically-typed languages • “Polymorphism is a way gaining some of the freedom of dynamic type checking without giving up the benefits of static checking.” (p. 128) Modern Programming Languages
Contract ProgrammingA Perspective for Polymorphic Interfaces • Methods are contracts with the user • Users must meet pre-conditions of a method • What the method expects from the client • Index in a certain range, for example • Method guarantees certain post-conditions • but only if the pre-conditions were met CS 3370 - Defensive Programming
Parties in ContractsClients and Suppliers • Clientsmust satisfy pre-conditions • They may benefit from post-conditions • But don’t have to • Suppliersmust satisfy post-conditions • They may assume the pre-conditions • But don’t have to • This affects inheritance… CS 3370 - Defensive Programming
Liskov Substitutability Principle • All derived objects must be able to substitute for a base class object • In contexts where public methods of the base class are used • Derived classes must not change the “rules of the game” CS 3370 - Defensive Programming
Contracts and Inheritance • Contracts are set by the base class • Derived classes must obey the base contract • Otherwise substitutability is compromised • Clients program to the contract • By using and understanding the base class interface and its conditions • And by using base/interface pointers • and letting polymorphism do its work invisibly • Example: contravar.cpp, contravar.d CS 3370 - Defensive Programming
Contracts and InheritanceSummary • “The problem for instances of B is how to be perfectly substitutable for instances of A. The only way to guarantee type safety and substitutability is to be equally or more liberal than A on inputs, and to be equally or more strict than A on outputs.”– Wikipedia • “Require no more; Promise no less” CS 3370 - Defensive Programming
Dynamic DispatchThe Mechanics of Subtype Polymorphism • In Java/C++/C#, the static type of a reference may be a superclass or interface of the actual runtime class • At runtime, the language system must find the right method for the actual class • the dynamic type • That’s dynamic dispatch: the hidden, implicit branch-on-class to implement method calls • Optional in C++ (must use virtual keyword) Modern Programming Languages
Multiple Dispatch • All of the examples we’ve seen of subtype polymorphism (or delegation) key off a single type (or object) to find the right method • p.f(x,y) considers only the dynamic type of p • x and y are not considered at runtime • Some languages (CLOS, Groovy, Perl 6) use all types involved to resolve the method lookup • “runtime overloading” • No one class/object “owns” the method
Double Dispatch Example Definitions for f(): What is the “most derived” function for the calls: c.f(x), c.f(w)?
An Ordering Perspective • List parameter combinations in “odometer order” (most general to most specific): • A,V * • A,W • A,X * • B,V • B,W • B,X * • C,V * • C,W • C,X • Reverse, keeping only existing methods: • C,V • B,X • A,X • A,V • To dispatch, test parameters in the order above for is-a, using RTTI • See doubledisp.cpp
Switching the Parameter Order • V A * • V B • V C * • W A • W B • W C • X A * • X B * • X C • X B * • X A * • V C * • V A * • See doubledisp-B.cpp
Multiple Dispatch • Any number of hierarchies/parameters may be used • Again, applicable methods are considered in “most derived” order • Supported natively by CLOS • Common Lisp Object System • “Generic Methods”
Multiple Dispatch Example • See multimeth.lsp, multimeth.cpp, multimeth.d