24
Conformance Object-Oriented Programming 236703 Spring 2008 1

Conformance Object-Oriented Programming 236703 Spring 2008 1

Embed Size (px)

Citation preview

Page 1: Conformance Object-Oriented Programming 236703 Spring 2008 1

Conformance

Object-Oriented Programming236703

Spring 2008

1

Page 2: Conformance Object-Oriented Programming 236703 Spring 2008 1

What’s Conformance?• Overriding: replace method body in

sub-class.• Polymorphism: subclass is usable

wherever superclass is usable.• Dynamic Biding: consequence of

overriding + polymorphism.– Select right method body

• Conformance: overriding and overridden should be equivalent

f(arg1, arg2){ xxx}

Superclass

f(arg1, arg2){ yyy}

Subclass

p

p->f(...)

p->f(...)

yyy should "conform" to xxx2

Page 3: Conformance Object-Oriented Programming 236703 Spring 2008 1

Conformance and Overriding• Ideally, an overriding method should be “semantically

compatible” with the overridden one.– All versions of “draw” should draw the object.– Not well-defined.– Impossible to guarantee!

• We must content ourselves with conformance in the following aspects:– Signature: input arguments, output arguments, input-

output arguments, return type, exceptions.– Access.– Contract: pre- and post-conditions, thrown exceptions.

3

Page 4: Conformance Object-Oriented Programming 236703 Spring 2008 1

“Same or better” Principle

Same or better: An overriding method should have at least the same functionality as the overridden method.

Overriding should not pose surprises to client.

More realistically: All that can be checked is static typing. The “type” of the overriding method should be a super-type

of the “type” of the overridden one.

The overriding method should have the same or more “calling patterns” as the overridden one.

4

Page 5: Conformance Object-Oriented Programming 236703 Spring 2008 1

Signature Conformance• Elements of signature

– Input arguments– Output arguments– Input-Output arguments– Return value– Exceptions

• Three alternatives:– No-variance: The type in signature cannot be changed.– Co-variance: Change of type in the signature is in the same

direction as that of the inheritance. – Contra-variance: Change of type in the signature is in the

opposite direction as that of the inheritance.5

Page 6: Conformance Object-Oriented Programming 236703 Spring 2008 1

Type of Arguments• For simplicity, we consider only input arguments.• Suppose that:

– m is a method of a base class– m takes an argument of class C– m is overridden by m’ in a derived class

• What is the type of the corresponding argument of m’ in the derived class?

Variance Type

No-variance

Contra-variance

Co-variance

Argument Type

Must be C

C or base class thereof

C or derived class thereof

Programming Language Example

C++, Java, C#

Sather

Eiffel

6

Page 7: Conformance Object-Oriented Programming 236703 Spring 2008 1

Covariance is Natural & Essential

DOUBLY LINKED

LIST

SINGLY LINKED

LIST

DOUBLY LINKED

NODE

SINGLY LINKED

NODEinsert()

insert()

More examples:Base: Graph and Node. Derived: MyGraph and MyNode

Base: Animal and Food. Derived: Cat and Bones7

Page 8: Conformance Object-Oriented Programming 236703 Spring 2008 1

Co-variance is Unsafe

class Food{}class Meat extends Food{}

class Animal{ void feed(Food f){

//... }}

class Lion extends Animal{ void feed(Meat m){

//... }}

class Food{}class Meat extends Food{}

class Animal{ void feed(Food f){

//... }}

class Lion extends Animal{ void feed(Meat m){

//... }}

void f(Animal a){ Food f = new Food(); a.feed(f);}

8

Page 9: Conformance Object-Oriented Programming 236703 Spring 2008 1

Co-variance and Static Typing• We have seen that co-variance is type unsafe.

– It may generate run-time type errors.

• Q: How can co-variance exist in Eiffel ?– Remember: Eiffel has static type checking

• A: Eiffel's type system has “holes”– Some messages will not have a compatible method in the receiver– The developer should be aware of that

• (Similar to programming in a dynamically typed language)

– A subclass with a covariant overriding is not a proper subtype of its superclass

• The compiler will allow assignability• But, you may get a “method-not-found” runtime error

• Possible solution: A whole-world-analysis– The compiler tries to find all possible assignments to a variable

• => Tries to predict the dynamic type of all variables

– Cannot be achieved in the general case9

Page 10: Conformance Object-Oriented Programming 236703 Spring 2008 1

Binary Methods

• A special case of a method with a covariant argument– The argument is of the same type as the receiver– Frequently occurs in many domains:– Comparison & Sorting, Arithmetics , Recursive Datastructures

(graphs)

class Point { int x, y; boolean same(Point p) { return x == p.x && y == p.y; }{class ColorPoint extends Point { Color color; boolean same(ColorPoint cp) { return x == cp.x && y == cp.y && color == cp.color; }}

class Point { int x, y; boolean same(Point p) { return x == p.x && y == p.y; }{class ColorPoint extends Point { Color color; boolean same(ColorPoint cp) { return x == cp.x && y == cp.y && color == cp.color; }}

10

Page 11: Conformance Object-Oriented Programming 236703 Spring 2008 1

Binary Methods (cont.)• Partial solutions

– like current (Eiffel)– Recursive genericity (Java)– Self type (LOOM)

• if used in a contra-variant position, then no subtyping

// Pseudo-code: LOOMclass Point { int x, y; boolean same(ThisClass p) { return x == p.x && y == p.y; }}class ColorPoint extends Point { Color color; boolean same(ThisClass cp) { return x == cp.x && y == cp.y && color == cp.color; }}Point p = new ColorPoint(); // Error – Not a subtype!

// Pseudo-code: LOOMclass Point { int x, y; boolean same(ThisClass p) { return x == p.x && y == p.y; }}class ColorPoint extends Point { Color color; boolean same(ThisClass cp) { return x == cp.x && y == cp.y && color == cp.color; }}Point p = new ColorPoint(); // Error – Not a subtype!

11

Page 12: Conformance Object-Oriented Programming 236703 Spring 2008 1

Return Type• Suppose that:

– m is a method of a base class– m returns a value of class C– m is overridden by m’ in a derived class

• Q: What is the return type of m’ in the derived class?• A: Covariance of return type is both natural and safe

12

Page 13: Conformance Object-Oriented Programming 236703 Spring 2008 1

Co-variance of Return Type is Safe

class Food{}class Meat extends Food{}

class Animal{ Food whatDoIEat(){

//... }}

class Lion extends Animal{ Meat whatDoIEat(){

//... }}

class Food{}class Meat extends Food{}

class Animal{ Food whatDoIEat(){

//... }}

class Lion extends Animal{ Meat whatDoIEat(){

//... }}

void f(Animal a){ Food f = a.whatDoIEat();}

13

Page 14: Conformance Object-Oriented Programming 236703 Spring 2008 1

Co-variance of Return Typeclass Employee {

public:virtual Employee *clone(void){

return new Employee(*this);}

};

class Manager: public Employee {public:

virtual Manager *clone(void){return new Manager(*this);

}};

class Employee {public:

virtual Employee *clone(void){return new Employee(*this);

}};

class Manager: public Employee {public:

virtual Manager *clone(void){return new Manager(*this);

}};

f(void){Employee *e1 = new Employee;Employee *e2 = new Manager;Employee *e3;e3 = e1->clone (); // e3 points to an Employeee3 = e2->clone (); // e3 points to a Manager

}

f(void){Employee *e1 = new Employee;Employee *e2 = new Manager;Employee *e3;e3 = e1->clone (); // e3 points to an Employeee3 = e2->clone (); // e3 points to a Manager

}

Using the virtual constructors

Define virtual constructors

Virtual constructors are an effective technique for implementing “cut” and shape palettes in a GUI draw application.

Virtual constructors are an effective technique for implementing “cut” and shape palettes in a GUI draw application.

14

Page 15: Conformance Object-Oriented Programming 236703 Spring 2008 1

Variance in C++, Java• As a rule: No Variance!

– Exact match in signature required between:• Overriding method• Overridden method

• If a method has a covariant argument...– ...It does not override the “old” method– Java: The new method overloads the old one– C++: The new method hides the old one

• Relaxation: Co-variance is allowed in return value– C++: Must have reference semantics (pointer or reference). – A later addition to both languages– Absolutely type safe– Quite useful

15

Page 16: Conformance Object-Oriented Programming 236703 Spring 2008 1

Covariance + Overloading = Headache

• This is a legal Java program– Recall: Covariance of arguments => Overloading

class A { boolean f(A a) { return true; }}class B extends A { boolean f(A a) { return false; } boolean f(B b) { return true; }}

void f() { A a = new A(); A ab = new B(); B b = new B(); a.f(a); a.f(ab); a.f(b); // true, true, true ab.f(a); ab.f(ab); ab.f(b); // false, false, false b.f(a); b.f(ab); b.f(b); // false, false, true}

class A { boolean f(A a) { return true; }}class B extends A { boolean f(A a) { return false; } boolean f(B b) { return true; }}

void f() { A a = new A(); A ab = new B(); B b = new B(); a.f(a); a.f(ab); a.f(b); // true, true, true ab.f(a); ab.f(ab); ab.f(b); // false, false, false b.f(a); b.f(ab); b.f(b); // false, false, true}

16

Page 17: Conformance Object-Oriented Programming 236703 Spring 2008 1

Hiding in C++• A similar program in C++

– Recall: Covariance of arguments => hiding

class A { boolean f(A a) { return true; }}class B extends A { boolean f(B b) { return false; }}

void f() { A a = new A(); A ab = new B(); B b = new B(); a.f(a); a.f(ab); a.f(b); // true, true, true ab.f(a); ab.f(ab); ab.f(b); // true, true, true b.f(a); b.f(ab); b.f(b); // compilation error!}

class A { boolean f(A a) { return true; }}class B extends A { boolean f(B b) { return false; }}

void f() { A a = new A(); A ab = new B(); B b = new B(); a.f(a); a.f(ab); a.f(b); // true, true, true ab.f(a); ab.f(ab); ab.f(b); // true, true, true b.f(a); b.f(ab); b.f(b); // compilation error!}

17

Page 18: Conformance Object-Oriented Programming 236703 Spring 2008 1

Conformance and # Arguments• Suppose that:

– m is a method of a base class taking n arguments– m is overridden by m’ in a derived class.

• Then, how many arguments should m’ have?– Exactly n:

• Most current programming languages.

– n or less:• It does not matter which arguments are omitted as long as naming is

consistent.

– n or more:• The BETA programming language (daughter of Simula).

• Note that adding arguments in an overriding method violates the “same or better” principle!

18

Page 19: Conformance Object-Oriented Programming 236703 Spring 2008 1

Conformance of Fields• Usually, fields can be read-from and written-to

– Similar to input-output arguments of a method– Thus, an overriding field should not change the field's type

• (No-variance)

– But, in most languages there's no overriding of fields...

• What about final fields?– They can only be read from – just like return values– Thus, covariance of final fields is OK

19

Page 20: Conformance Object-Oriented Programming 236703 Spring 2008 1

Conformance of Exceptions• Suppose that:

– m is a method of a base class that throws exceptions of types {e1…en}

– m is overridden by m’ in a derived class– m ’ throws exceptions of types {x1…xm}

• What is the relationship between {e1…en} and {x1…xm}?

C++• exceptions are not part of the signature• C++ throws clause is checked at run-timeJava• Recall: a calling function should handle the callee’s exceptions

– Catch or declare

• Therefore, for each xi (1i m) we require that there is ej (1j n) where xi is a subtype of ej

20

Page 21: Conformance Object-Oriented Programming 236703 Spring 2008 1

Access ConformanceAll versions of a method should have the same visibility.

– Smalltalk: All methods are public.– Eiffel: Inheritance and export are orthogonal.

• Sub-class is not strictly a sub-type.

– Java: Subclass can only improve the visibility of a method– C++: Not enforced, may lead to breaking of encapsulation.

class X{public:

virtual void f(void);};

class Y: public X{ private:

void f(void); } y, *py = &y;

X *px = py;

py->f(); // Error! Y::f is private.px->f(); // OK! (but breaks encapsulation.)

class X{public:

virtual void f(void);};

class Y: public X{ private:

void f(void); } y, *py = &y;

X *px = py;

py->f(); // Error! Y::f is private.px->f(); // OK! (but breaks encapsulation.)

21

Page 22: Conformance Object-Oriented Programming 236703 Spring 2008 1

Friendship and OverridingA friend of base class is not necessarily a friend of the derived class.

class X{friend void amigo();virtual void f();

};

class Y: public X{void f();

};

void amigo(){

Y* y = new Y();

y->f(); // Error! Y::f is private.

X* x = y; // Simple up casting.

x->f(); // OK! now the same Y::f is accessible. }

class X{friend void amigo();virtual void f();

};

class Y: public X{void f();

};

void amigo(){

Y* y = new Y();

y->f(); // Error! Y::f is private.

X* x = y; // Simple up casting.

x->f(); // OK! now the same Y::f is accessible. }

22

Page 23: Conformance Object-Oriented Programming 236703 Spring 2008 1

Eiffel: Design by Contractclass ACCOUNT

feature {NONE}

balance: INTEGER

count: INTEGER

feature {ANY}

deposit(sum:INTEGER) is

require

non_negative: sum >= 0

do

balance := balance + sum;

count := count + 1;

ensure

balance >= 0;

count = old count + 1;

end

end

class ACCOUNT

feature {NONE}

balance: INTEGER

count: INTEGER

feature {ANY}

deposit(sum:INTEGER) is

require

non_negative: sum >= 0

do

balance := balance + sum;

count := count + 1;

ensure

balance >= 0;

count = old count + 1;

end

end

23

Page 24: Conformance Object-Oriented Programming 236703 Spring 2008 1

Contract Conformance• Rules of contract conformance.

– Pre-condition: Overriding method must demand the same or less from its client.

– Post-condition: Overriding method must promise the same or more to its client.

• Rationale: “Same or better principle”.• Contracts and Inheritance in Eiffel:

– Pre and post conditions are inherited.– They can be refined, but never replaced.

• Pre-condition refinement: old_pre_condition or new_pre_condition

• Post-condition refinement: old_post_condition and new_post_condition

24