SOEN6461: Software Design Methodologies Yann-Gal Guhneuc Yann-Gal - - PowerPoint PPT Presentation

soen6461 software design methodologies
SMART_READER_LITE
LIVE PREVIEW

SOEN6461: Software Design Methodologies Yann-Gal Guhneuc Yann-Gal - - PowerPoint PPT Presentation

SOEN6461: Software Design Methodologies Yann-Gal Guhneuc Yann-Gal Guhneuc Encapsulation, inheritance and types, polymorphism (overriding/overloading), abstraction and types This work is licensed under a Creative Commons


slide-1
SLIDE 1

Yann-Gaël Guéhéneuc

This work is licensed under a Creative Commons Attribution-NonCommercial- ShareAlike 3.0 Unported License

Yann-Gaël Guéhéneuc

SOEN6461: Software Design Methodologies

Encapsulation, inheritance and types, polymorphism (overriding/overloading), abstraction and types

slide-2
SLIDE 2

2/128

Programming Languages (1/4)

 Programming languages have been around

since the 1800s

– In 1801, Joseph Marie Jacquard invented a “code” to represent sewing loom arm movements on punch cards

slide-3
SLIDE 3

3/128

Programming Languages (1/4)

http://www.nature.com/nature/journal/v444/n7119/abs/nature05357.html

slide-4
SLIDE 4

4/128

Programming Languages (1/4)

http://arstechnica.com/information-technology/2014/03/gears-of-war-when-mechanical-analog-computers-ruled-the-waves/

slide-5
SLIDE 5

5/128

Programming Languages (2/4)

– In 1842-43, Ada Lovelace designed a “code” to compute Bernouilli numbers on Charles Babbage's Analytical Engine

slide-6
SLIDE 6

6/128

Programming Languages (3/4)

– In 1936, Alan Turing invented the Turing machine and a “code” to program it – In the 1950s, the first modern programming language appear

  • FORTRAN in 1955 by John Backus et al.
  • LISP in 1958 by John McCarthy et al.
  • COBOL in 1959 by Grace Murray Hopper

– Since then, many more have been created…

slide-7
SLIDE 7

7/128

Programming Languages (3/4)

– In 1936, Alan Turing invented the Turing machine and a “code” to program it – In the 1950s, the first modern programming language appear

  • FORTRAN in 1955 by John Backus et al.
  • LISP in 1958 by John McCarthy et al.
  • COBOL in 1959 by Grace Murray Hopper

– Since then, many more have been created…

http://rigaux.org/language-study/diagram.png

slide-8
SLIDE 8

8/128

Programming Languages (4/4)

 The design and implementation of the newer

programming languages all attempt

– To solve problems (real or perceived) in previous languages – To rise the level of abstraction and hide away the hardware systems – To provide constructs that are closer to the domain model or adapt better to hardware

slide-9
SLIDE 9

9/128

Programming Languages (4/4)

 The design and implementation of the newer

programming languages all attempt

– To solve problems (real or perceived) in previous languages – To rise the level of abstraction and hide away the hardware systems – To provide constructs that are closer to the domain model or adapt better to hardware

Civilization advances by extending the number of important operations that we can perform without thinking about them. —Alfred North Whitehead (1911)

slide-10
SLIDE 10

10/128

Structured Programming

 Before 1968, (modern) programming

languages were mostly unstructured

– No explicit loops (for, while…) – Instruction goto + line number / labels

slide-11
SLIDE 11

11/128

Structured Programming

 Before 1968, (modern) programming

languages were mostly unstructured

– No explicit loops (for, while…) – Instruction goto + line number / labels Problem: lack of structure Solution: structures

slide-12
SLIDE 12

12/128

Structured Programming

 Before 1968, (modern) programming

languages were mostly unstructured

– No explicit loops (for, while…) – Instruction goto + line number / labels

 Main (most famous) criticism by Edsger

Dijkstra in “Go To Statement Considered Harmful”, CACM, 1968

Problem: lack of structure Solution: structures

slide-13
SLIDE 13

13/128

Information Hiding

 Between 1968 and 1972, programming languages

began to be structured but data and functions were all visible

– No explicit packaging – No explicit access control

slide-14
SLIDE 14

14/128

Information Hiding

 Between 1968 and 1972, programming languages

began to be structured but data and functions were all visible

– No explicit packaging – No explicit access control

Problem: lack of packaging and access control Solution: information hiding

slide-15
SLIDE 15

15/128

Information Hiding

 Between 1968 and 1972, programming languages

began to be structured but data and functions were all visible

– No explicit packaging – No explicit access control

 Main (most famous) criticism by David Parnas in

“On the Criteria to Be Used in Decomposing Systems Into Modules”, CACM, 1972 Problem: lack of packaging and access control Solution: information hiding

slide-16
SLIDE 16

16/128

Information Hiding

Problem: implementation of information hiding Solution: encapsulation (in OO languages)

slide-17
SLIDE 17

17/128

Information Hiding

 Information hiding can be realised through

– Encapsulation

  • Typical in object-oriented programming languages

– Lexical closures

  • Typical in functional programming languages

Problem: implementation of information hiding Solution: encapsulation (in OO languages)

slide-18
SLIDE 18

18/128

Information Hiding

 Information hiding can be realised through

– Encapsulation

  • Typical in object-oriented programming languages

– Lexical closures

  • Typical in functional programming languages

Problem: implementation of information hiding Solution: encapsulation (in OO languages)

slide-19
SLIDE 19

19/128

Encapsulation

 In the 1980s, object-oriented programming

languages became popular, in part because they propose encapsulation

 Encapsulation is

– A language mechanism for restricting access to some of the object's components

  • Modifiers public, protected, private…

– A language construct to bundle data with the methods

  • perating on that data
  • Classes and objects
slide-20
SLIDE 20

20/128

Encapsulation

 In the 1980s, object-oriented programming

languages became popular, in part because they propose encapsulation

 Encapsulation is

– A language mechanism for restricting access to some of the object's components

  • Modifiers public, protected, private…

– A language construct to bundle data with the methods

  • perating on that data
  • Classes and objects

Fundamental to OO programming languages

slide-21
SLIDE 21

21/128

Object-oriented Programming

 The “first”, canonical class-based object-oriented

programming language is Smalltalk

– Developed between 1972 and 1980 by Kay et al. at Xerox Parc

 Fundamental concepts

– Encapsulation – Inheritance – Polymorphism – Abstraction

slide-22
SLIDE 22

22/128

Object-oriented Programming

 Fundamental concepts

– Encapsulation – Inheritance (typing) – Polymorphism (overriding, overloading) – Abstraction (typing)

slide-23
SLIDE 23

23/128

Inheritance, Types

 Definition

– A way to reuse code of existing objects, to establish a subtype from an existing object, or both, depending upon programming language support [Wikipedia] – Different between class-based and prototype- based programming languages Problem: reuse code and categorise classes Solution: inheritance and typing

slide-24
SLIDE 24

24/128

Inheritance, Types

 Class-based, typically Java

– Reuse of code

class CommonCode { protected void foo() { } } public class Reuser1 extends CommonCode { public void method1() { this.foo(); } } public class Reuser2 extends CommonCode { public void method2() { this.foo(); } }

slide-25
SLIDE 25

25/128

Inheritance, Types

 Class-based, typically Java

– Subtyping, overriding

public interface Type { void foo1(); void bar1(); } public class SubType implements Type { public void bar1() { // TODO Auto-generated method stub } public void foo1() { // TODO Auto-generated method stub } }

slide-26
SLIDE 26

26/128

Inheritance, Types

 Reuse and subtyping

combined

– To factor out code, e.g., in PADL – To create a taxonomy, e.g., in Java libraries

slide-27
SLIDE 27

27/128

Inheritance, Types

 Reuse and subtyping combined

package aPackage; public interface Measure { int getValue(); } abstract class AbstractMeasure { public int getValue() { System.out.println("Before..."); return this.getRealValue(); } abstract int getRealValue(); } // Need a factory... public class Length extends AbstractMeasure implements Measure { public int getRealValue() { return 1; } } public class Size extends AbstractMeasure implements Measure { public int getRealValue() { return 2; } }

slide-28
SLIDE 28

28/128

Inheritance, Types

 Reuse and subtyping combined

package aPackage; public interface Measure { int getValue(); } abstract class AbstractMeasure { public int getValue() { System.out.println("Before..."); return this.getRealValue(); } abstract int getRealValue(); } // Need a factory... public class Length extends AbstractMeasure implements Measure { public int getRealValue() { return 1; } } public class Size extends AbstractMeasure implements Measure { public int getRealValue() { return 2; } }

Distinguishing between reuse and subtyping

slide-29
SLIDE 29

29/128

Inheritance, Types

Why distinguish between reuse and subtyping?

slide-30
SLIDE 30

30/128

Inheritance, Types

Why distinguish between reuse and subtyping?

slide-31
SLIDE 31

31/128

Inheritance, Types

 Prototype-based, typically JavaScript

– Reuse of code

var commonCode = new CommonCode(); commonCode.foo(); var reuser1 = new Reuser1(); reuser1.method1(); function CommonCode() { // No instance variables. } CommonCode.prototype.foo = function foo() { document.write("foo()<br>"); }; function Reuser1() { // No instance variables. } Reuser1.prototype = new CommonCode(); Reuser1.prototype.constructor = Reuser1; Reuser1.prototype.method1 = function method1() { this.foo(); document.write("in method1()<br>"); };

slide-32
SLIDE 32

32/128

Inheritance, Types

 Prototype-based, typically JavaScript

– “Subtyping”

var type = new Type(); type.foo(); type.bar(); var subtype = new SubType(); subtype.foo(); subtype.bar(); function Type() { } Type.prototype.foo = function foo() { throw new Error("This is an abstract method!"); }; Type.prototype.bar = function bar() { throw new Error("This is an abstract method!"); }; function SubType() { } SubType.prototype = new Type(); SubType.prototype.constructor = SubType; SubType.prototype.foo = function foo() { document.write("foo()<br>"); }; SubType.prototype.bar = function bar() { document.write("bar()<br>"); };

slide-33
SLIDE 33

33/128

Inheritance, Types

 Reuse and subtyping combined

function AbstractMeasure() { } AbstractMeasure.prototype.getValue = function getValue() { document.write("Some code before...<br>"); return this.getRealValue(); }; AbstractMeasure.prototype.getRealValue = function getRealValue() { throw new Error("Abstract method!"); }; function Length() { } Length.prototype = new AbstractMeasure(); Length.prototype.constructor = Length; Length.prototype.getRealValue = function getRealValue() { document.write("Specific code.<br>"); return 1; };

slide-34
SLIDE 34

34/128

Inheritance, Types

 Reuse and subtyping combined

function AbstractMeasure() { } AbstractMeasure.prototype.getValue = function getValue() { document.write("Some code before...<br>"); return this.getRealValue(); }; AbstractMeasure.prototype.getRealValue = function getRealValue() { throw new Error("Abstract method!"); }; function Length() { } Length.prototype = new AbstractMeasure(); Length.prototype.constructor = Length; Length.prototype.getRealValue = function getRealValue() { document.write("Specific code.<br>"); return 1; };

No real distinction between reuse and “subtyping”

slide-35
SLIDE 35

35/128

Inheritance, Types

 Java vs. JavaScript

– Make no mistake: JavaScript is no less “powerful” or “clean” than Java! – Different paradigms

  • Class + Imperative + Strongly-typed
  • Prototype + Functional + Dynamically-typed

– Different implementations of the paradigms

  • Visibility
  • Pairs name + value
slide-36
SLIDE 36

36/128

Polymorphism

 Definition

– Subtype polymorphism, almost universally called polymorphism in object-oriented programming – The ability to create a variable, a function, or an

  • bject that has more than one form

– Superset of overloading, overriding Problem: change behaviour of concrete objects Solution: polymorphism

slide-37
SLIDE 37

37/128

Overriding

 Definition

– A language feature that allows a subclass or a child class to provide a specific implementation of a method that is already provided by one of its super / parent classes

slide-38
SLIDE 38

38/128

Overriding

 Class-based, typically Java

public class SuperClass { public void foo() { System.out.println("One implementation."); } } public class SubClass extends SuperClass { public void foo() { super.foo(); System.out.println("Another implementation."); } }

slide-39
SLIDE 39

39/128

Overriding

 Class-based, typically Java

– Declared type vs. Concrete type – Overriding is resolved by the dynamic type of the receiver, not its static type

public class Main { public static void main(final String[] args) throws InstantiationException, IllegalAccessException { final SuperClass superClass = new SubClass(); superClass.foo(); final SubClass subClass = new SubClass(); ((SuperClass) subClass).foo(); ((SuperClass) subClass.getClass().getSuperclass().newInstance()).foo(); } }

slide-40
SLIDE 40

40/128

Overriding

 Class-based, typically Java

– Declared type vs. Concrete type – Overriding is resolved by the dynamic type of the receiver, not its static type

public class Main { public static void main(final String[] args) throws InstantiationException, IllegalAccessException { final SuperClass superClass = new SubClass(); superClass.foo(); final SubClass subClass = new SubClass(); ((SuperClass) subClass).foo(); ((SuperClass) subClass.getClass().getSuperclass().newInstance()).foo(); } }

Distinction between declared type and concrete type

slide-41
SLIDE 41

41/128

Overriding

 Class-based, typically Java

– Declared type vs. Concrete type – Overriding is resolved by the dynamic type of the receiver, not its static type

public class Main { public static void main(final String[] args) throws InstantiationException, IllegalAccessException { final SuperClass superClass = new SubClass(); superClass.foo(); final SubClass subClass = new SubClass(); ((SuperClass) subClass).foo(); ((SuperClass) subClass.getClass().getSuperclass().newInstance()).foo(); } }

Distinction between declared type and concrete type Runtime dispatch

slide-42
SLIDE 42

42/128

Overriding

 Class-based, typically Java

– Declared type vs. Concrete type – Overriding is resolved by the dynamic type of the receiver, not its static type

public class Main { public static void main(final String[] args) throws InstantiationException, IllegalAccessException { final SuperClass superClass = new SubClass(); superClass.foo(); final SubClass subClass = new SubClass(); ((SuperClass) subClass).foo(); ((SuperClass) subClass.getClass().getSuperclass().newInstance()).foo(); } }

Distinction between declared type and concrete type Runtime dispatch Reflection

slide-43
SLIDE 43

43/128 var subClass = new SubClass(); subClass.foo();

Overriding

 Prototype-based, typically JavaScript

– Declared type vs. concrete type

function SuperClass() { } SuperClass.prototype.foo = function foo() { document.write("One implementation...<br>"); }; function SubClass() { } SubClass.prototype = new SuperClass(); SubClass.prototype.constructor = SubClass; SubClass.prototype.parent = SuperClass.prototype; SubClass.prototype.foo = function foo() { this.parent.foo.call(this); document.write("Another implementation...<br>"); };

slide-44
SLIDE 44

44/128 var subClass = new SubClass(); subClass.foo();

Overriding

 Prototype-based, typically JavaScript

– Declared type vs. concrete type

function SuperClass() { } SuperClass.prototype.foo = function foo() { document.write("One implementation...<br>"); }; function SubClass() { } SubClass.prototype = new SuperClass(); SubClass.prototype.constructor = SubClass; SubClass.prototype.parent = SuperClass.prototype; SubClass.prototype.foo = function foo() { this.parent.foo.call(this); document.write("Another implementation...<br>"); };

No type declaration  Unlike Java!

slide-45
SLIDE 45

45/128 var subClass = new SubClass(); subClass.foo();

Overriding

 Prototype-based, typically JavaScript

– Declared type vs. concrete type

function SuperClass() { } SuperClass.prototype.foo = function foo() { document.write("One implementation...<br>"); }; function SubClass() { } SubClass.prototype = new SuperClass(); SubClass.prototype.constructor = SubClass; SubClass.prototype.parent = SuperClass.prototype; SubClass.prototype.foo = function foo() { this.parent.foo.call(this); document.write("Another implementation...<br>"); };

No type declaration  Unlike Java! No super  Unlike Java!

slide-46
SLIDE 46

46/128

Overriding

 Java vs. JavaScript

– Make no mistake: JavaScript is no less “powerful” or “clean” than Java! – Different paradigms

  • Class + Imperative + Strongly-typed
  • Prototype + Functional + Dynamically-typed

– Different implementations of the paradigms

  • Runtime method dispatch
  • Possibility to change the context of a call
slide-47
SLIDE 47

47/128

Overloading

 Definition

– Methods that have the same name but different signatures inside the same class or a class hierarchy

slide-48
SLIDE 48

48/128

Overloading

 Class-based, typically Java

public class Point { public boolean equals(final Object anObject) { System.out.println("One implementation."); return false; } public boolean equals(final Point aPoint) { System.out.println("Another implementation."); return false; } } public class Main { public static void main(final String[] args) { final Point p1 = new Point(); final Point p2 = new Point(); final Object o = p1; System.out.println(p1.equals(p2)); System.out.println(o.equals(p2)); System.out.println(p1.equals(o)); } }

slide-49
SLIDE 49

49/128

Overloading

 Class-based, typically Java

public class Point { public boolean equals(final Object anObject) { System.out.println("One implementation."); return false; } public boolean equals(final Point aPoint) { System.out.println("Another implementation."); return false; } } public class Main { public static void main(final String[] args) { final Point p1 = new Point(); final Point p2 = new Point(); final Object o = p1; System.out.println(p1.equals(p2)); System.out.println(o.equals(p2)); System.out.println(p1.equals(o)); } } Another implementation. false

slide-50
SLIDE 50

50/128

Overloading

 Class-based, typically Java

public class Point { public boolean equals(final Object anObject) { System.out.println("One implementation."); return false; } public boolean equals(final Point aPoint) { System.out.println("Another implementation."); return false; } } public class Main { public static void main(final String[] args) { final Point p1 = new Point(); final Point p2 = new Point(); final Object o = p1; System.out.println(p1.equals(p2)); System.out.println(o.equals(p2)); System.out.println(p1.equals(o)); } } Another implementation. false One implementation. false

slide-51
SLIDE 51

51/128

Overloading

 Class-based, typically Java

public class Point { public boolean equals(final Object anObject) { System.out.println("One implementation."); return false; } public boolean equals(final Point aPoint) { System.out.println("Another implementation."); return false; } } public class Main { public static void main(final String[] args) { final Point p1 = new Point(); final Point p2 = new Point(); final Object o = p1; System.out.println(p1.equals(p2)); System.out.println(o.equals(p2)); System.out.println(p1.equals(o)); } } Another implementation. false One implementation. false One implementation. false

slide-52
SLIDE 52

52/128

Overloading

 Class-based, typically Java

– The equals() method in Point takes a Point instead of an Object as an argument – It does not override equals in Object – It is just an overloaded alternative – Overloading is resolved by the static type of the argument, not its run-time type

slide-53
SLIDE 53

53/128

Overloading

 Class-based, typically

Java

– Using the static type of the argument is natural in a strongly-typed language... – Else how could the program compile?

final Point p1 = new Point(); final Object o = p1; System.out.println(o.equals(p2));

slide-54
SLIDE 54

54/128

Overloading

 Class-based, typically

Java

– Using the static type of the argument is natural in a strongly-typed language... – Else how could the program compile?

// Compiled from Main.java (version 1.6 : 50.0, super bit) public class ca.concordial.soeb6461.overloading.Main { // Method descriptor #6 ()V // Stack: 1, Locals: 1 public Main(); 0 aload_0 [this] 1 invokespecial java.lang.Object() 4 return […] // Method descriptor #15 ([Ljava/lang/String;)V // Stack: 3, Locals: 4 public static void main(java.lang.String[] args); […] 32 aload_3 [o] 33 aload_2 [p2] 34 invokevirtual java.lang.Object.equals(java.lang.Object) : boolean 37 invokevirtual java.io.PrintStream.println(boolean) : void 40 getstatic java.lang.System.out : java.io.PrintStream final Point p1 = new Point(); final Object o = p1; System.out.println(o.equals(p2));

slide-55
SLIDE 55

55/128

Overloading

 Prototype-based, typically JavaScript

– The issue here is really that JavaScript is dynamically-typed – Overloading just does not make sense!

slide-56
SLIDE 56

56/128

Overloading

 Prototype-based, typically JavaScript

– Implementing the look-up table manually

// addMethod - By John Resig (MIT Licensed) function addMethod(object, name, fn){ var old = object[ name ];

  • bject[ name ] = function(){

if ( fn.length == arguments.length ) return fn.apply( this, arguments ); else if ( typeof old == 'function' ) return old.apply( this, arguments ); }; } When control enters the execution context of a function an arguments object is created. The arguments object has an array-like structure with an indexed property for each passed argument and a length property equal to the total number of parameters supplied by the caller.

slide-57
SLIDE 57

57/128

Overloading

 Prototype-based, typically JavaScript

– Implementing the look-up table manually

function Users(){} addMethod(Users.prototype, "find", function(){ // Find all users... }); addMethod(Users.prototype, "find", function(name){ // Find a user by name }); addMethod(Users.prototype, "find", function(first, last){ // Find a user by first and last name }); var users = new Users(); users.find(); // Finds all users.find("John"); // Finds users by name users.find("John", "Resig"); // Finds users by first and last name users.find("John", "E", "Resig"); // Does nothing

slide-58
SLIDE 58

58/128

Overloading

 Java vs. JavaScript

– Make no mistake: JavaScript is no less “powerful” or “clean” than Java! – Different paradigms

  • Class + Imperative + Strongly-typed
  • Prototype + Functional + Dynamically-typed

– Different implementations of the paradigms

  • Static method dispatch
  • Dispatch based on name and number of arguments
slide-59
SLIDE 59

59/128

Polymorphism

 Definition (recalled)

– Subtype polymorphism, almost universally called polymorphism in object-oriented programming – The ability to create a variable, a function, or an

  • bject that has more than one form

– Superset of overloading, overriding Problem: change behaviour of concrete objects Solution: polymorphism

slide-60
SLIDE 60

60/128

Polymorphism

 Definition

– Subtype polymorphism is all about type-safety and the “contract” between a superclass and its subclasses – It is all about pre- and post-conditions

  • And directly related to co- and contra-variance
slide-61
SLIDE 61

61/128

slide-62
SLIDE 62

62/128

Polymorphism –

Liskov’s Substitution Principle

 Barbara Liskov

– Born 7 November 1939 – Mother of the Liskov’s substitution principle – IEEE J. von Neumann Medal in 2004 – ACM Turing Award in 2008 – Cf. http://en.wikipedia.org/wiki/ Liskov_substitution_principle

Barbara Liskov *1939

slide-63
SLIDE 63

63/128

Polymorphism – Liskov’s Substitution Principle

 Liskov’s substitution principle

– Context

  • 1987

– Object-oriented programming is increasingly popular

– Principle

  • Let q(x) be a property provable about objects x
  • f type T. Then q(y) should be true for objects y
  • f type S where S is a subtype of T
slide-64
SLIDE 64

64/128

Polymorphism – Liskov’s Substitution Principle

– Principle (cont’d)

  • Behavioural sub-typing is different and stronger than

the concept of sub-typing in type theory

  • In type theory

– Contravariance of parameters: a parameter of type T can accept object of type S, where S is a sub-type of T – Covariance of return type: the return type can be “enlarged” from T to S

  • In addition

– Pre-conditions cannot be stronger in a sub-type – Post-conditions cannot be weaker in a sub-type – The sub-type S must preserve the invariants of type T

slide-65
SLIDE 65

65/128

Polymorphism – Liskov’s Substitution Principle

 Definition

– If S is a subtype of T, then objects of type T may be replaced with objects of type S (objects of type S may be substitutes for objects of type T) without altering any of the desirable properties

  • f S (correctness, task, etc.)

T S P

slide-66
SLIDE 66

66/128

Polymorphism – Liskov’s Substitution Principle

 This principle defines the notions of

generalization/specialization formally

 Class S is correctly defined as a specialization of T if the

following are true

– For each object s of class S there is an object t of class T such that the expected behavior of any program P defined in terms of T is unchanged if s is substituted for t

 Then

– S is a said to be a subtype of T – Any instance of S can stand for an instance of T without any undesired effect on client classes – Any future extension (new subclasses) will not affect existing clients

From Giuliano Antoniol’s slides INF6305

slide-67
SLIDE 67

67/128

Polymorphism – Liskov’s Substitution Principle

class Rectangle : public Shape { private: int w, h; public: virtual void set_width(int wi) { w=wi; } virtual void set_height(int he) { h=he; } } class Square : public Rectangle { public: void set_width(int w) { Rectangle::set_height(w); Rectangle::set_width(w); } void set_height(int h) { set_width(h); } } void foo(Rectangle *r) { // This is the client r->set_width(5); r->set_height(4); assert((r->get_width()*r->get_height()) == 20); // Oracle }

  • If r is instantiated at run time with an instance of square, behaviour observed by

client is different (width*height == 16)

  • Observed behaviour unexpected and may lead to problems
  • Square should be defined as subclass of Shape, not Rectangle

From Giuliano Antoniol’s slides for INF6305.

slide-68
SLIDE 68

68/128

Polymorphism – Liskov’s Substitution Principle

 Class S is correctly defined as a

specialization of T then we say that S is compatible with T

T S P

slide-69
SLIDE 69

69/128

Polymorphism

 Class-based, typically Java

class SuperClass { Object getSomething() { return new Object(); } } class SubClass extends SuperClass { String getSomething() { return new String(); } } public class CovarianceOfReturnTypes { public static void main(final String[] args) { final SuperClass superClass = new SubClass(); System.out.println( Object.class.isAssignableFrom(superClass.getSomething().getClass())); } }

slide-70
SLIDE 70

70/128

Polymorphism

 Class-based, typically Java

final SuperClass superClass = new SubClass(); final SubClass subClass = new SubClass();

slide-71
SLIDE 71

71/128

Polymorphism

 Class-based, typically Java

class SuperClass { Object getSomething() { return new Object(); } } class SubClass extends SuperClass { String getSomething() { return new String(); } } public class CovarianceOfReturnTypes { public static void main(final String[] args) { final SuperClass superClass = new SubClass(); System.out.println( Object.class.isAssignableFrom(superClass.getSomething().getClass())); } }

slide-72
SLIDE 72

72/128

Polymorphism

 Class-based, typically Java

class SuperClass { Object getSomething() { return new Object(); } } class SubClass extends SuperClass { String getSomething() { return new String(); } } public class CovarianceOfReturnTypes { public static void main(final String[] args) { final SuperClass superClass = new SubClass(); System.out.println( Object.class.isAssignableFrom(superClass.getSomething().getClass())); } }

Covariance of return type  Objects returned by getSomething in any subclass are always compatible with that expected by the superclass

slide-73
SLIDE 73

73/128

Polymorphism

 Class-based, typically Java

class SuperClass { String getSomething() { return new Object(); } } class SubClass extends SuperClass { Object getSomething() { return new String(); } } public class ContravarianceOfReturnTypes { public static void main(final String[] args) { final SuperClass superClass = new SubClass(); // This whole piece of code is not legal in Java! For example only. final String result = superClass.getSomething(); } }

slide-74
SLIDE 74

74/128

Polymorphism

 Class-based, typically Java

class SuperClass { String getSomething() { return new Object(); } } class SubClass extends SuperClass { Object getSomething() { return new String(); } } public class ContravarianceOfReturnTypes { public static void main(final String[] args) { final SuperClass superClass = new SubClass(); // This whole piece of code is not legal in Java! For example only. final String result = superClass.getSomething(); } }

If contavariance of return type  Objects returned by getSomething in a subclass would not be compatible with that expected by the superclass

slide-75
SLIDE 75

75/128

Polymorphism

 Class-based, typically Java

class SuperClass { Object getSomething() { return new Object(); } } class SubClass extends SuperClass { String getSomething() { return new String(); } } public class CovarianceOfReturnTypes { public static void main(final String[] args) { final SuperClass superClass = new SubClass(); System.out.println( Object.class.isAssignableFrom(superClass.getSomething().getClass())); } }

slide-76
SLIDE 76

76/128

Polymorphism

 Class-based, typically Java

class SuperClass { Object getSomething() { return new Object(); } } class SubClass extends SuperClass { String getSomething() { return new String(); } } public class CovarianceOfReturnTypes { public static void main(final String[] args) { final SuperClass superClass = new SubClass(); System.out.println( Object.class.isAssignableFrom(superClass.getSomething().getClass())); } }

Post-conditions in the subtype must be the same as or stronger than in the supertype

slide-77
SLIDE 77

77/128

Polymorphism

 Class-based, typically Java

class SuperClass { Object getSomething() { return new Object(); } } class SubClass extends SuperClass { String getSomething() { return new String(); } } public class CovarianceOfReturnTypes { public static void main(final String[] args) { final SuperClass superClass = new SubClass(); System.out.println( Object.class.isAssignableFrom(superClass.getSomething().getClass())); } }

Post-conditions in the subtype must be the same as or stronger than in the supertype

Post-condition

slide-78
SLIDE 78

78/128

Polymorphism

 Class-based, typically Java

class SuperClass { Object getSomething() { return new Object(); } } class SubClass extends SuperClass { String getSomething() { return new String(); } } public class CovarianceOfReturnTypes { public static void main(final String[] args) { final SuperClass superClass = new SubClass(); System.out.println( Object.class.isAssignableFrom(superClass.getSomething().getClass())); } }

Post-conditions in the subtype must be the same as or stronger than in the supertype

Post-condition Covariance

slide-79
SLIDE 79

79/128

Polymorphism

 Class-based, typically Java

class SuperClass { void getSomething(final String aParameter) { System.out.println("One implementation..."); } } class SubClass extends SuperClass { void getSomething(final Object aParameter) { System.out.println("Another implementation..."); } } public class ContravarianceOfArgumentTypes { public static void main(final String[] args) { final SubClass subClass = new SubClass(); subClass.getSomething(new Object()); subClass.getSomething(""); } }

slide-80
SLIDE 80

80/128

Polymorphism

 Class-based, typically Java

class SuperClass { void getSomething(final String aParameter) { System.out.println("One implementation..."); } } class SubClass extends SuperClass { void getSomething(final Object aParameter) { System.out.println("Another implementation..."); } } public class ContravarianceOfArgumentTypes { public static void main(final String[] args) { final SubClass subClass = new SubClass(); subClass.getSomething(new Object()); subClass.getSomething(""); } }

Contravariance of arguments types  Objects used by getSomething in any subclass are always narrower to allow calling the super method

slide-81
SLIDE 81

81/128

Polymorphism

 Class-based, typically Java

class SuperClass { void getSomething(final Object aParameter) { System.out.println("One implementation..."); } } class SubClass extends SuperClass { void getSomething(final String aParameter) { System.out.println("Another implementation..."); } } public class ContravarianceOfArgumentTypes { public static void main(final String[] args) { final SubClass subClass = new SubClass(); // This piece of code is not legal in Java! For example only. subClass.getSomething(""); } }

slide-82
SLIDE 82

82/128

Polymorphism

 Class-based, typically Java

class SuperClass { void getSomething(final Object aParameter) { System.out.println("One implementation..."); } } class SubClass extends SuperClass { void getSomething(final String aParameter) { System.out.println("Another implementation..."); } } public class ContravarianceOfArgumentTypes { public static void main(final String[] args) { final SubClass subClass = new SubClass(); // This piece of code is not legal in Java! For example only. subClass.getSomething(""); } }

Covariance of arguments types  Objects used by getSomething in any subclass would confuse the compiler: which method to use?

slide-83
SLIDE 83

83/128

Polymorphism

 Class-based, typically Java

class SuperClass { void getSomething(final String aParameter) { System.out.println("One implementation..."); } } class SubClass extends SuperClass { void getSomething(final Object aParameter) { System.out.println("Another implementation..."); } } public class ContravarianceOfArgumentTypes { public static void main(final String[] args) { final SubClass subClass = new SubClass(); subClass.getSomething(new Object()); subClass.getSomething(""); } }

slide-84
SLIDE 84

84/128

Polymorphism

 Class-based, typically Java

class SuperClass { void getSomething(final String aParameter) { System.out.println("One implementation..."); } } class SubClass extends SuperClass { void getSomething(final Object aParameter) { System.out.println("Another implementation..."); } } public class ContravarianceOfArgumentTypes { public static void main(final String[] args) { final SubClass subClass = new SubClass(); subClass.getSomething(new Object()); subClass.getSomething(""); } }

Pre-conditions in the subtype must be the same as or weaker than in the supertype

slide-85
SLIDE 85

85/128

Polymorphism

 Class-based, typically Java

class SuperClass { void getSomething(final String aParameter) { System.out.println("One implementation..."); } } class SubClass extends SuperClass { void getSomething(final Object aParameter) { System.out.println("Another implementation..."); } } public class ContravarianceOfArgumentTypes { public static void main(final String[] args) { final SubClass subClass = new SubClass(); subClass.getSomething(new Object()); subClass.getSomething(""); } }

Pre-conditions in the subtype must be the same as or weaker than in the supertype

Pre-condition

slide-86
SLIDE 86

86/128

Polymorphism

 Class-based, typically Java

class SuperClass { void getSomething(final String aParameter) { System.out.println("One implementation..."); } } class SubClass extends SuperClass { void getSomething(final Object aParameter) { System.out.println("Another implementation..."); } } public class ContravarianceOfArgumentTypes { public static void main(final String[] args) { final SubClass subClass = new SubClass(); subClass.getSomething(new Object()); subClass.getSomething(""); } }

Pre-conditions in the subtype must be the same as or weaker than in the supertype

Pre-condition Contravariance

slide-87
SLIDE 87

87/128

Polymorphism

 Contra-variance in more depth…  Thank you http://www.jdoodle.com,

Firefox Abduction!, and Eclipse compilers

slide-88
SLIDE 88

88/128

slide-89
SLIDE 89

89/128

with v1.3

slide-90
SLIDE 90

90/128

slide-91
SLIDE 91

91/128

slide-92
SLIDE 92

92/128

https://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29

slide-93
SLIDE 93

93/128

Not

Another implementation… Another implementation…

https://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29

slide-94
SLIDE 94

94/128

slide-95
SLIDE 95

95/128

Valid! Valid!

slide-96
SLIDE 96

96/128

slide-97
SLIDE 97

97/128

Workaround!

slide-98
SLIDE 98

98/128

https://stackoverflow.com/questions/2995926/why-is-there-no-parameter-contra-variance-for-overriding

slide-99
SLIDE 99

99/128

Thank you to Willian Flageol for the example

slide-100
SLIDE 100

100/128

https://underscore.io/blog/posts/2015/11/04/late-binding-and-overloading.html

slide-101
SLIDE 101

101/128

https://coderwall.com/p/dlqvnq/simple-example-for-scala-covariance-contravariance-and-invariance

slide-102
SLIDE 102

102/128

Generics!

Should be contrasted with Java

https://coderwall.com/p/dlqvnq/simple-example-for-scala-covariance-contravariance-and-invariance

slide-103
SLIDE 103

103/128

Polymorphism

 In Java

– https://stackoverflow.com/questions/3861132/ how-would-contravariance-be-used-in-java- generics

 In Eiffel and Sather

– http://www1.icsi.berkeley.edu/~sather/Document ation/EclecticTutorial/node15.html

slide-104
SLIDE 104

104/128

Polymorphism

 Class-based, typically Java

– Dispatching

public class SuperClass { public void foo(final Object anObject) { System.out.println("One implementation."); } } public class SubClass extends SuperClass { public void foo(final Object anObject) { super.foo(this); System.out.println("Another implementation."); } public void foo(final String aString) { super.foo(this); System.out.println("Yet another implementation."); } } public class Main { public static void main(final String[] args) { final SuperClass superClass = new SubClass(); superClass.foo(""); final SubClass subClass = new SubClass(); ((SuperClass) subClass).foo(""); } }

slide-105
SLIDE 105

105/128

Polymorphism

 Class-based, typically Java

– Dispatching

public class SuperClass { public void foo(final Object anObject) { System.out.println("One implementation."); } } public class SubClass extends SuperClass { public void foo(final Object anObject) { super.foo(this); System.out.println("Another implementation."); } public void foo(final String aString) { super.foo(this); System.out.println("Yet another implementation."); } } public class Main { public static void main(final String[] args) { final SuperClass superClass = new SubClass(); superClass.foo(""); final SubClass subClass = new SubClass(); ((SuperClass) subClass).foo(""); } } One implementation. Another implementation. One implementation. Another implementation.

slide-106
SLIDE 106

106/128

Polymorphism

 Class-based, typically Java

– Dispatching (cont’d)

public class SuperClass { public void foo(final String anObject) { System.out.println("One implementation."); } } public class SubClass extends SuperClass { public void foo(final Object anObject) { super.foo(""); System.out.println("Another implementation."); } public void foo(final String aString) { super.foo(""); System.out.println("Yet another implementation."); } } public class Main { public static void main(final String[] args) { final SuperClass superClass = new SubClass(); superClass.foo(""); final SubClass subClass = new SubClass(); ((SuperClass) subClass).foo(""); } }

slide-107
SLIDE 107

107/128

Polymorphism

 Class-based, typically Java

– Dispatching (cont’d)

public class SuperClass { public void foo(final String anObject) { System.out.println("One implementation."); } } public class SubClass extends SuperClass { public void foo(final Object anObject) { super.foo(""); System.out.println("Another implementation."); } public void foo(final String aString) { super.foo(""); System.out.println("Yet another implementation."); } } public class Main { public static void main(final String[] args) { final SuperClass superClass = new SubClass(); superClass.foo(""); final SubClass subClass = new SubClass(); ((SuperClass) subClass).foo(""); } } One implementation. Yet another implementation. One implementation. Yet another implementation.

slide-108
SLIDE 108

108/128

Polymorphism

 Functional-based, typically CommonLisp

– Dispatching

(defgeneric test (x y) (:documentation "Returns the type of the two arguments)) (defmethod test ((x number) (y number)) '(num num)) (defmethod test ((i integer) (y number)) '(int num)) (defmethod test ((x number) (j integer)) '(num int)) (defmethod test ((i integer) (j integer)) '(int int))

slide-109
SLIDE 109

109/128

Polymorphism

 Functional-based, typically CommonLisp

– Dispatching

(defgeneric test (x y) (:documentation "Returns the type of the two arguments)) (defmethod test ((x number) (y number)) '(num num)) (defmethod test ((i integer) (y number)) '(int num)) (defmethod test ((x number) (j integer)) '(num int)) (defmethod test ((i integer) (j integer)) '(int int)) (test 1 1) => (int int) (test 1 1/2) => (int num) (test 1/2 1) => (num int) (test 1/2 1/2) => (num num)

slide-110
SLIDE 110

110/128

Polymorphism

 Java vs. CommonLisp

– Make no mistake: Java is no less “powerful” or “clean” than CommonLisp! – Different paradigms

  • Class + Imperative + Strongly-typed
  • Functional + Strongly/Dynamically-typed

– Different implementations of the paradigms

  • Single method dispatch
  • Multiple method dispatch
slide-111
SLIDE 111

111/128

Abstraction, Types

 Object-oriented programming languages

typically offer

– Concrete classes – Abstract classes – Pure abstract classes / interfaces

  • Types

Problem: package reusable data and behaviour Solution: abstraction and typing

slide-112
SLIDE 112

112/128

Abstraction, Types

 The virtues of abstraction is that “the user of

the abstraction can forget the details of the implementation of the abstraction.”

– By Richard Gabriel, Patterns of Software, Oxford Univeristy Press, 1998

 A class should have only one reason to

change

– By Robert C. Martin

slide-113
SLIDE 113

113/128

Abstraction, Types

 Take a sort algorithm, e.g., an insertion sort

package ca.concordia.soen6461; import java.util.List; public class InsertionSort<E> { public List<E> sort(final List<E> aList) { final List<E> temporaryList = null; // Some implementation... return temporaryList; } } public class Client { public static void main(final String[] args) { final InsertionSort<String> s = new InsertionSort<String>(); final List<String> l = null; s.sort(l); } }

slide-114
SLIDE 114

114/128

Abstraction, Types

 Take a sort algorithm, e.g., an insertion sort

package ca.concordia.soen6461; import java.util.List; public class InsertionSort<E> { public List<E> sort(final List<E> aList) { final List<E> temporaryList = null; // Some implementation... return temporaryList; } } public class Client { public static void main(final String[] args) { final InsertionSort<String> s = new InsertionSort<String>(); final List<String> l = null; s.sort(l); } }

Everything that InsertionSort

  • ffers is available to Client
slide-115
SLIDE 115

115/128

Abstraction, Types

 Problems with InsertionSort

– Exposes the implementation of the sort

  • What if we want to replace this implementation by

another?

– Exposes the public interface of the class

  • What if we want to share some public method with
  • ther library class BUT NOT with our clients?
slide-116
SLIDE 116

116/128

Abstraction, Types

 We can “abstract” all sort algorithms

package ca.concordia.soen6461; import java.util.List; public abstract class AbstractSort<E> { public abstract List<E> sort(final List<E> aList); public void someHelperMethod() { // Some implementation... } protected void someOtherHelperMethod() { // Some implementation... } } public class Client { public static void main(final String[] args) { final AbstractSort<String> s = new InsertionSort<String>(); final List<String> l = null; s.sort(l); } }

slide-117
SLIDE 117

117/128

Abstraction, Types

 We can “abstract” all sort algorithms

package ca.concordia.soen6461; import java.util.List; public abstract class AbstractSort<E> { public abstract List<E> sort(final List<E> aList); public void someHelperMethod() { // Some implementation... } protected void someOtherHelperMethod() { // Some implementation... } } public class Client { public static void main(final String[] args) { final AbstractSort<String> s = new InsertionSort<String>(); final List<String> l = null; s.sort(l); } }

Only public methods of AbstractSort are available to Client

slide-118
SLIDE 118

118/128

Abstraction, Types

 Advantage with the abstract class

– Code reuse

 Problems with AbstractSort

– Exposes the public interface of the class

  • What if we want to share some public methods with
  • ther library classes BUT NOT with our clients?

– Exposes the “partial” type of the sort

  • What if we want to use an implementation of a sort

algorithm that is NOT a subclass of AbstractSort?

slide-119
SLIDE 119

119/128

Abstraction, Types

 We can abstract all sort algorithms

package ca.concordia.soen6461; import java.util.List; public interface ISort<E> { public List<E> sort(final List<E> aList); } public class Client { public static void main(final String[] args) { final ISort<String> s = new InsertionSort<String>(); final List<String> l = null; s.sort(l); } }

slide-120
SLIDE 120

120/128

Abstraction, Types

 We can abstract all sort algorithms

package ca.concordia.soen6461; import java.util.List; public interface ISort<E> { public List<E> sort(final List<E> aList); } public class Client { public static void main(final String[] args) { final ISort<String> s = new InsertionSort<String>(); final List<String> l = null; s.sort(l); } }

Only public methods in ISort are available to Client

slide-121
SLIDE 121

121/128

Abstraction, Types

 Advantages with the interface (type)

– Hides completely the implementation from the client code – Allows any classes to offer a new sort algorithm by implementing the interface ISort

slide-122
SLIDE 122

122/128

Abstraction, Types

 Advantages with the interface (type)

– Hides completely the implementation from the client code – Allows any classes to offer a new sort algorithm by implementing the interface ISort

Allow the development of an “economy”, e.g., for Java collections :

  • Java class libraries
  • Apache Commons
  • Javolutions
slide-123
SLIDE 123

123/128

Abstraction, Types

 Other examples, from worst to best

  • 1. ArrayList BankAccount.getBankAccounts()

Vector Shape.getPoints()

  • 2. List BankAccount.getBankAccounts()

List Shape.getPoints()

  • 3. Iterator BankAccount.getBankAccounts()

Iterator Shape.getPoints()

slide-124
SLIDE 124

124/128

Abstraction, Types

 Other examples, from worst to best

  • 1. ArrayList BankAccount.getBankAccounts()

Vector Shape.getPoints()

  • 2. List BankAccount.getBankAccounts()

List Shape.getPoints()

  • 3. Iterator BankAccount.getBankAccounts()

Iterator Shape.getPoints()

slide-125
SLIDE 125

125/128

Abstraction, Types

 Other examples, from worst to best

  • 1. ArrayList BankAccount.getBankAccounts()

Vector Shape.getPoints()

  • 2. List BankAccount.getBankAccounts()

List Shape.getPoints()

  • 3. Iterator BankAccount.getBankAccounts()

Iterator Shape.getPoints()

slide-126
SLIDE 126

126/128

Conclusion (1/3)

 Fundamental concepts of object-oriented

programming languages evolved to solve specific problems

slide-127
SLIDE 127

127/128

Conclusion (2/3)

 Lessons to learn

– These concepts do not require a class-based

  • bject-oriented programming language

– They depend on implementation choices

  • Static vs. Dynamic method dispatch
  • Single vs. Multiple method dispatch

– Visitor design pattern

  • Covariance vs. Contra-variance
slide-128
SLIDE 128

128/128

Conclusion (3/3)

 In the following, we will see how other

problems that could NOT (yet) be solved by programming languages will be solved by using specific

– Architectures – Designs – Techniques