Title: Inheritance Techniques
1Inheritance Techniques
- Subcontracting
- Anchored Types
2Inheritance is subcontracting.
- class C ...
- void p(S s)
- s.r()
-
-
- Call C c T t
- c.p(t)
- class S
- void r()
-
- class T extends S
- void r()
-
- Spec pre-post conditions
3- Parent Invariant Rule
- The invariants of all the parents (and therefore,
the ancestors) of a class apply to the class
itself. - Assertion Redeclaration Rule
- A routine redeclaration may only replace the
original precondition by one equal or weaker, and
the original postcondition by one equal or
stronger. - P S.r() Q
- P T.r() Q
- P gt P and Q gt Q
- (Cf. Rule of consequence)
- The postcondition associated with a 0-ary routine
redeclared as an attribute manifests itself as an
additional class invariant.
4Odds and Ends
- Global Inheritance Structure
- Java has a tree-structured class hierarchy (with
null-type treated separately). - The features of universal interest (such as
equal(_), clone(), toString(), locks for
concurrency, etc) are in class java.lang.Object. - Frozen Features
- In Java, final can be applied to a class, a
method, and a field to prohibit extension,
redefinition, and change, respectively. (This is
for security reasons, for freezing the semantics,
and for defining a constant, respectively.)
5Anchored Declarations Covariance
- class Device feature
- alternate Device
- set_alternate(aDevice)
- is do
- alternate a
- end
- end
- class Printer inherit
- Device feature
- alternate Printer
- set_alternate(aPrinter)
- is do
- alternate a
- end
- end
- Usually, redeclaration uses same
signature to introduce or substitute a new
algorithm. Eiffel also supports redeclaration by
type specialization. - class Device feature
- alternate like Current
- set_alternate
- (alike Current)
- is do
- alternate a
- end
- end
6- class LinkG feature
- item G
- right LinkG
- put_right(nLinkG)
- is do end
- ...
- end
- class BiLinkG inherit
- LinkG feature
- item G
- left, right like Current
- put_right(n like left)
- is do end
- put_left(n like left)
- is do end
- ...
- end
Link
BiLink
- Type Redeclaration Rule
- A redeclaration of a feature may replace the
type of the feature, or the type of a formal, by
any type that conforms to the original. - This is a syntactic and purely static rule,
with no effect on run-time objects.
7- class ColoredPoint
- extends Point
- Color c
- boolean eq(ColoredPoint p)
- return ( super(p)
- ( c p.c ) )
- // unsatisfactory override
- class ColoredPoint
- extends Point
- Color c
- boolean eq(Point p)
- if (p instanceof
- ColoredPoint)
- return ( super(p) )
- ( c p.c )
- else return false
- // redeclare
- class Point
- int x,y
- boolean eq(Point p)
- return ( x p.x)
- ( y p.y)
-
- class ColoredPoint
- extends Point
- Color c
- boolean eq(Point p)
- return ( x p.x)
- ( y p.y)
- ...
- // unsatisfactory
8Static Typing
- Type violation x.f(args)
- There is no f applicable to object associated
with x, or args is not acceptable. - A language is statically typed if it is
equipped with consistency rules, enforceable by a
compiler, whose observance by the software text
guarantees that no execution of the system can
cause a type violation. (E.g., Eiffel, Ada, ML,
etc.) - A language is strongly typed if it can guarantee
the absence of type violations. (E.g., Java,
Smalltalk, etc.)
9- Nature of the beast Trying to guarantee that
no computation will ever fail forces one to
disallow computations that might succeed. (E.g,
n integer 2.0 is illegal in Ada.) - Benefits Reliability, Readability, Efficiency
- Typing vs Binding
- Typing When do we know for sure that at run-time
there will be an operation corresponding to f
and applicable to the object attached to x (with
the argument arg). - Polymorphism
- Binding Which operation will the call execute?
- Redeclaration
10Typing problems
- Interaction with
- polymorphism
- (Covariance)
- Device d new
- CD-Drive()
- Printer p new
- Printer()
- d.set_alternate(p)
- Anchored declaration does not prevent type
violation, but Java encoding seems to work.
- Interaction between redeclaration and
descendant hiding - Java prohibits method redeclaration that
reduce visibility (e.g., from public to
private). O/w, it can always be beaten by
promoting subclass object and using dynamic
binding.
11Covariance and Contravariance
- If we could override a method changing the
formal types or return types, then - A change that moves down the inheritance
hierarchy, making it more specific, is said to be
covariant. - A change that moves up the inheritance hierarchy
is said to be contravariant.
12Subtyping (substituitivity) Problem
- class Parent
- void test (covar Mammal,
- contravar Mammal) boolean
-
- class Child extends Parent
- void test (covar Cat,
- contravar Animal) boolean
-
- Parent aValue new Child()
- aValue.test(new Dog(), new Mammal())
13Contravariance Problem
- class Parent
- Mammal test ( )
- return new Cat()
-
-
- class Child extends Parent
- Animal test ()
- return new Bird()
-
-
- Parent aValue new Child()
- Mammal result aValue.test()
14Safe Change in C (Java 5, Cool)
- class Parent
- public
- Parent clone () return new Parent()
-
- class Child public Parent
- public
- Child clone () return new Child()
15Signature Rule for Function Subtyping
class A public RA m (PA p)
class B extends A public RB m (PB p)
- RB must be a subtype of RA RB lt RA
- PB must be a supertype of PA PB gtPA
- covariant for results, contravariant for
parameters
16Implementation
17Single Inheritance of Data Fields
- class A
- int a
-
- class C extends A
- int d
-
- class B extends A
- int b,c
-
- class D extends B
- int e
A
a
D
a
b
c
e
18(contd)
- Observe that for reusing inherited binary code of
a parent method, it is necessary that the layout
of the child object be an extension of the layout
of the parent object. That is, the common fields
have the same index in the two object layouts. - this pointer is unchanged in a polymorphic
assignment.
19Class Descriptors for Dynamic Method Lookup
- class A
- int x
- int f()
-
- class B extends A
- int g()
- class C extends B
- int g()
-
- class D extends C
- int y
- int f()
20A_f
A
B
C
D
21(contd)
- Observe that for the polymorphism to work
correctly, a call to a parent method should
invoke code for the childs overriding method.
This can be accomplished by having the index of
the (overridden) parent method be the same as the
index of the (overriding) child method. That is,
the common methods have the same index in the
method table. - this pointer is unchanged in a polymorphic
assignment.
22Multiple Inheritance of Data Fields
- class A
- int a
-
- class B
- int b,c
-
- class C extends A
- int d
-
- class D extends
- A, B, C
- int e
d
23Fields Offsets in Descriptors for Multiple
Inheritance
A
1
D
24Object Layout and Class Descriptors for Dynamic
Method Lookup
- class A
- int a
- int f()
-
- class B
- int b, c
- int g()
- class C
- int d
- int h()
-
- class D extends A, B, C
- int e
- int f()
- int h()
25C Approach
26- For memory efficient layout of instance fields
and convenient reuse of inherited method code,
the sub-objects of D corresponding to B and to C
should resemble a B and a C instance
respectively. (Resemblance to an A and a D
instance is automatic.) - This requires introducing method table reference
slot, and adjusting this pointer for
coercion/casting.
27C vtables for D-object
A D
D_f
0
l
a
B
B_g
0
d
b,c
C
-d
D_h
d
e
28(Minor Change)
- class A
- int a
- int f()
-
- class B
- int b, c
- int g()
- class C
- int d
- int h()
-
- class D extends A, B, C
- int e
- int g()
29C vtables for D-object
A D
A_f
0
l
a
B
D_g
-l
d
b,c
C
0
C_h
d
e
30Dynamic Linking
- Global analysis is not feasible if a class can be
loaded at run-time (such as in Java). Instead, it
requires incremental approach. - Hash table may be used in the class descriptor to
map field names to offsets, and method names to
method pointers. - instanceof and dynamic type checks can be
implemented efficiently using a display of
pointers to ancestor class descriptors.