Modules and OOP.

Download Report

Transcript Modules and OOP.

Modules and
Object-Oriented Programming
Modules (Packages)
Programming in the Large
Information hiding
• Limit the ways in which one part of the
program can access another.
• Allow proprietary software to be called
without the technique being published.
Separate compilation.
Separate compilation
and linking
Compiler produces
• Import table: List of imported symbols
• Export table: List of exported symbols
• Relocation table: List of “absolute” addresses
used in code.
Imported symbol in code compiles into
reference in import table.
Absolute address in code is listed in relocation
table.
Two-pass linker
Pass 1: Find absolute addresses for all
static entities (objects and code).
Extract library functions used.
Pass 2: Replace all imported and
“absolute” addresses in compiled code
with true absolute addresses.
Package declaration (Ada)
package Stacks is
type Stack is private;
procedure Push(S: in out Stack;
X: in out Integer)
procedure Pop(S: in out Stack;
X: out Integer)
function “=“(S,T: Stack) return Boolean;
(from Barnes, Programming in Ada-95)
private
Max: constant := 100;
type IntegerVector is array(Integer range <> of
Integer)
type Stack is
record S: IntegerVector(1 .. Max);
Top: Integer range (0 .. Max) := 0;
end record;
end;
Package body
package body Stacks is
procedure Push(S: in out Stack;
X: in Integer) is
begin S.Top := S.Top+1;
S.S(S.Top) := X;
end Push
etc.
Package use
declare
use Stacks;
St : Stack;
begin Push(St,N);
…
Pop(St,M);
end;
Information hiding in packages
type Stack: Fields Stack.S and Stack.Top
are externally visible.
type Stack is private:
Only assignment, =, and /= are visible.
type Stack is limited private: Only visible
functions are those declared so by user.
Object-oriented programming
• Information hiding as in modules
• Viewpoint shift. A module is just a hunk
o’ code. An object is an active data
structure.
• Class hierarchy and inheritance
• Dynamic method binding
Let X be an object of class C with method
M. Is “X.M(N)” anything more than
syntactic sugar for “C_M(X,N)”?
• Yes, with dynamic method binding.
• With inheritance, syntactic sugar is not
to be sneezed at.
Class definition
• Data members (fields)
• Subroutine members (methods)
• Base class and derived class.
Class definition in Java
public class Rectangle {
private float xSpan,ySpan;
public Rectangle() { this(1.0,1.0); }
public Rectangle(float x, float y) {
setRect(x,y); }
public void setRect(float x, float y) {
xSpan=x; ySpan=y; }
public float xTop() { return xSpan; }
public float xBot() { return 0.0; } … }
Derived class in Java
public class locatedRectangle extends
Rectangle {
private float xL, yL; // lower left corner
public locatedRectangle() {
setCorner(0.0,0.0); }
public void setCorner(float xa, float ya) {
xL = xa; yL = ya; }
public float xTop() { return xL+xSpan; }
public float xBot() { return xL; } … }
Creating an object in Java
{ locatedRectangle R, Q; // declaration
float X;
R = new locatedRectangle();
Q = R;
X = R.xTop(); }
/* R and Q are pointers to the same heap
object. Constructors are invoked in
order from superclass to subclass.*/
Dynamic method binding
Rectangle A;
locatedRectangle R1,R2;
R1 = new locatedRectangle();
A = R1; // Cast from sub to super
R2 = (locatedRectangle) A; // downcast
… A.xTop() …; // dynamic method: uses
// xTop() for locatedRectangle
// not for Rectangle
“final” classes and methods
A class declared “final” cannot be have a
derived class.
A method declared “final” cannot be
overridden.
Any declared use of a final class or
method can be resolved at compile
time, and saves the overhead of
dynamic disambiguation.
Dynamic method binding:
Implementation in vtables
Method access through vtables
Rectangle A;
… A.xTop() …
compiles to
Follow A to the heap object.
Follow vtable pointer to vtable.
Follow vtable[1] to code for A.xTop
In all classes derived from Rectangle, xTop is
vtable[1].
Abstract classes
A method with no body is abstract.
A class with an abstract method is
abstract.
Abstract classes cannot have objects;
they can only have derived classes.
Used to provide a “hook” for dynamic
method binding.
Example: Apply a function to
every member of an array.
We will discuss four solutions to this:
• Abstract classes in OOP
• Interfaces in OOP
• Generics
• Functional parameters
Example: applier.java
abstract class ArrayApplier {
public abstract int f(int x);
public void ApplyToArray(int[] A, int[] B) {
for (int i=0; i < A.length; i++)
B[i] =f(A[i]); } }
class applyIncr extends ArrayApplier {
public int f(int i) { return i+1; } }
Using the abstract class
public class applier {
public static void main(String args[]) {
int A[] = new int[] {1,2,3};
int B[] = new int[3];
applyIncr Incr = new applyIncr();
applyDouble Doub = new applyDoub();
Incr.ApplyToArray(A,B);
Doub.ApplyToArray(A,B); } }
Interfaces
•
•
•
•
Interface I: A collection of abstract methods
Class C implements I, instantiates Q.
Method M declares a variable of type I.
M is called with object of type C. M’s call to X.Q uses
C’s definition of Q.
interface I { public void Q(); }
class C implements I {
public void Q() { Body of C’s Q }}
public void M(I X) { … X.Q(); … }
C P = new C(); // In some other method
M(P);
Multiple implementations
A class can extend only one base class,
but may implement many interfaces.
Some say that this achieves a kind of
multiple inheritance.
Example: applier2.java
interface IntFun { public int f(int x); }
class Incr implements IntFun {
public int f(int i) { return i+1; }
public class applier2 {
public static void
ApplyToArray(IntFun Q, int[] A, int[] B) {
for (i=0; i<A.length; i++) B[i]=Q.f(A[i]);}
applier2.java (cntd)
public static void main(String args[]) {
int A[] = new int[] { 1,2,3 };
int B[] = new int[3];
Incr Inc = new Incr();
ApplyToArray(Inc,A,B):
} } // end applier2
TestVisitor.java: Features
• Hiding of data fields: Standard OOP
practice. Small methods are compiled
inline. E.g. x.getChild() is compiled as if
it were x.child.
• Dynamic method biding of
(x.getChild()).accept to A’s accept or B’s
accept.
• “Visitor” design pattern for coding
TestInterface.java: Features
• Use of interface allows different visitors
over the same data structure. Different
visitors may process nodes differently or
may choose different paths to traverse.
• Replace visitA and visitB by overloading
visit. Doesn’t affect functionality or
expressivity. Elegant or confusing?
Point of the visitor design
A data structure with multiple types. Here A and
B. More realistically, an expression tree with
additive nodes, multiplicative nodes etc.
Various operations to do on this data structure.
Each operation acts differently on different
types. Here MyVisitor and DumbVisitor. More
realistically, evaluate, pretty print, optimize,
search, etc.
You don’t want to build the code for the
operations into the data structure types.
You don’t want to write in the operation
if (x instanceOf A) processA((A) x)
else if (x instanceOf B) processB((B) x)
else …
which is ugly, type unsafe, and slow.
Overloading and Inheritance
The type of the formal parameter must be
a supertype of the actual parameter.
A method name may be overloaded with
parameters that are subtypes of one
another. (See TestOverload.java)
If so, use the most specific match.
If “most specific match” is ambiguous,
compiler error. (TestOverload1.java)
C++ OOP vs. Java
• Objects can be stack variables
• Static method binding is the default. To get
dynamic binding, declare method as “virtual”.
• Multiple inheritance: A derived type may
extend several base types. Complicated rules
for constructors etc. If method call is
ambiguous, error. Dynamic binding is
difficult.