Week 03 - 2 - Encapsulation, Inheritance, Types, Overloading, Overriding, Polymorphism, and Abstract

This preview shows page 1 out of 109 pages.

Unformatted text preview: SOEN6461: Software Design Methodologies Yann-Gaël Guéhéneuc Encapsulation, inheritance and types, polymorphism (overriding/overloading), abstraction and types This work is licensed under a Creative Commons Attribution-NonCommercialShareAlike 3.0 Unported License 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 2/109 Programming Languages (1/4) 3/109 Programming Languages (1/4) 4/109 Programming Languages (2/4) – In 1842-43, Ada Lovelace designed a “code” to compute Bernouilli numbers on Charles Babbage's Analytical Engine 5/109 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… 6/109 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… 7/109 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 8/109 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) 9/109 Structured Programming Before 1968, (modern) programming languages were mostly unstructured – No explicit loops (for, while…) – Instruction goto + line number / labels 10/109 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 11/109 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 Main (most famous) criticism by Edsger Dijkstra in “Go To Statement Considered Harmful”, CACM, 1968 12/109 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 13/109 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 14/109 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 Main (most famous) criticism by David Parnas in “On the Criteria to Be Used in Decomposing Systems Into Modules”, CACM, 1972 15/109 Information Hiding Problem: implementation of information hiding Solution: encapsulation (in OO languages) 16/109 Information Hiding Problem: implementation of information hiding Solution: encapsulation (in OO languages) Information hiding can be realised through – Encapsulation • Typical in object-oriented programming languages – Lexical closures • Typical in functional programming languages 17/109 Information Hiding Problem: implementation of information hiding Solution: encapsulation (in OO languages) Information hiding can be realised through – Encapsulation • Typical in object-oriented programming languages – Lexical closures • Typical in functional programming languages 18/109 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 operating on that data • Classes and objects 19/109 Encapsulation Fundamental to OO programming languages 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 operating on that data • Classes and objects 20/109 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 21/109 Object-oriented Programming Fundamental concepts – Encapsulation – Inheritance (typing) – Polymorphism (overriding, overloading) – Abstraction (typing) 22/109 Inheritance, Types Problem: reuse code and categorise classes Solution: inheritance and typing 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 prototypebased programming languages 23/109 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(); } } 24/109 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 } } 25/109 Inheritance, Types Reuse and subtyping combined – To factor out code, e.g., in PADL – To create a taxonomy, e.g., in Java libraries 26/109 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(); } public class Length extends AbstractMeasure implements Measure { public int getRealValue() { return 1; } } public class Size extends AbstractMeasure implements Measure { abstract int getRealValue(); public int getRealValue() { return 2; } } // Need a factory... } 27/109 Distinguishing between reuse and subtyping 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(); } public class Length extends AbstractMeasure implements Measure { public int getRealValue() { return 1; } } public class Size extends AbstractMeasure implements Measure { abstract int getRealValue(); public int getRealValue() { return 2; } } // Need a factory... } 28/109 Inheritance, Types Why distinguish between reuse and subtyping? 29/109 Inheritance, Types Why distinguish between reuse and subtyping? 30/109 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>"); }; 31/109 Inheritance, Types Prototype-based, typically JavaScript – “Subtyping” var type = new Type(); type.foo(); type.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!"); }; var subtype = new SubType(); subtype.foo(); subtype.bar(); 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>"); }; 32/109 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; }; 33/109 Inheritance, Types No real distinction between reuse and “subtyping” 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; }; 34/109 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 35/109 Polymorphism Problem: change behaviour of concrete objects Solution: polymorphism Definition – Subtype polymorphism, almost universally called polymorphism in object-oriented programming – The ability to create a variable, a function, or an object that has more than one form – Superset of overloading, overriding 36/109 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 37/109 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."); } } 38/109 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(); } } 39/109 Overriding Distinction between declared type and concrete type 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(); } } 40/109 Overriding Distinction between declared type and concrete type Runtime dispatch 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(); } } 41/109 Overriding Distinction between declared type and concrete type Runtime dispatch Class-based, typically Java Reflection – 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(); } } 42/109 Overriding Prototype-based, typically JavaScript 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>"); }; – Declared type vs. concrete type var subClass = new SubClass(); subClass.foo(); 43/109 Overriding No type declaration Unlike Java! Prototype-based, typically JavaScript 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>"); }; – Declared type vs. concrete type var subClass = new SubClass(); subClass.foo(); 44/109 Overriding No type declaration Unlike Java! No super Unlike Java! Prototype-based, typically JavaScript 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>"); }; – Declared type vs. concrete type var subClass = new SubClass(); subClass.foo(); 45/109 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 46/109 Overloading Definition – Methods that have the same name but different signatures inside the same class or a class hierarchy 47/109 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)); } } 48/109 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 49/109 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 50/109 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 51/109 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 52/109 Overloading Class-based, typically Java – Using the static type of the argument is natural in a stronglytyped language... – Else how could the program compile? final Point p1 = new Point(); final Object o = p1; System.out.println(o.equals(p2)); 53/109 Overloading Class-based, typically Java – Using the static type of the argument is natural in a stronglytyped language... – Else how could the program compile? final Point p1 = new Point(); final Object o = p1; System.out.println(o.equals(p2)); // Compiled from Main.java (version 1.6 : 50.0, super bit) public class ca.polymtl.gigl.log6306.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 54/109 Overloading Prototype-based, typically JavaScript – The issue here is really that JavaScript is dynamically-typed – Overloading just does not make sense! 55/109 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 ]; object[ 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 e...
View Full Document

  • Left Quote Icon

    Student Picture

  • Left Quote Icon

    Student Picture

  • Left Quote Icon

    Student Picture