soen6461 software design methodologies
play

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


  1. Inheritance, Types  Prototype-based, typically JavaScript – “Subtyping” function Type() { } Type.prototype.foo = function foo() { throw new Error("This is an abstract method!"); var type = }; new Type(); Type.prototype.bar = function bar() { type.foo(); throw new Error("This is an abstract method!"); type.bar(); }; function SubType() { } SubType.prototype = new Type(); SubType.prototype.constructor = SubType; SubType.prototype.foo = function foo() { document.write("foo()<br>"); var subtype = }; new SubType(); SubType.prototype.bar = function bar() { subtype.foo(); document.write("bar()<br>"); subtype.bar(); }; 32/128

  2. 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/128

  3. No real distinction between Inheritance, Types 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/128

  4. 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/128

  5. 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/128

  6. 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/128

  7. 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/128

  8. 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/128

  9. Distinction between declared type and Overriding 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/128

  10. Distinction between declared type and Overriding 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/128

  11. Distinction between declared type and Overriding 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/128

  12. 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/128

  13. No type declaration  Unlike Java! 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(); 44/128

  14. No type declaration  Unlike Java! Overriding 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/128

  15. 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/128

  16. Overloading  Definition – Methods that have the same name but different signatures inside the same class or a class hierarchy 47/128

  17. 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/128

  18. 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(); Another implementation. final Point p2 = new Point(); false final Object o = p1; System. out.println(p1.equals(p2)); System. out.println(o.equals(p2)); System. out.println(p1.equals(o)); } } 49/128

  19. 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(); Another implementation. final Point p2 = new Point(); false final Object o = p1; One implementation. System. out.println(p1.equals(p2)); false System. out.println(o.equals(p2)); System. out.println(p1.equals(o)); } } 50/128

  20. 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(); Another implementation. final Point p2 = new Point(); false final Object o = p1; One implementation. System. out.println(p1.equals(p2)); false System. out.println(o.equals(p2)); One implementation. System. out.println(p1.equals(o)); false } } 51/128

  21. 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/128

  22. 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)); 53/128

  23. // Compiled from Main.java (version 1.6 : 50.0, Overloading super bit) public class ca.concordial.soeb6461.overloading.Main { // Method descriptor #6 ()V // Stack: 1, Locals: 1 public Main();  Class-based, typically 0 aload_0 [this] Java 1 invokespecial java.lang.Object() 4 return – Using the static type of […] the argument is natural in a strongly-typed // Method descriptor #15 ([Ljava/lang/String;)V // Stack: 3, Locals: 4 language... public static void main(java.lang.String[] args); – Else how could the […] 32 aload_3 [o] program compile? 33 aload_2 [p2] 34 invokevirtual java.lang.Object.equals(java.lang.Object) : boolean final Point p1 = new Point(); 37 invokevirtual final Object o = p1; java.io.PrintStream.println(boolean) : void System. out.println(o.equals(p2)); 40 getstatic java.lang.System.out : java.io.PrintStream 54/128

  24. Overloading  Prototype-based, typically JavaScript – The issue here is really that JavaScript is dynamically-typed – Overloading just does not make sense ! 55/128

  25. 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 equal to the total number of parameters supplied by the caller. 56/128

  26. 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 57/128

  27. 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 58/128

  28. Polymorphism Problem: change behaviour of concrete objects Solution: polymorphism  Definition (recalled) – 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 59/128

  29. 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 60/128

  30. 61/128

  31. Polymorphism – Liskov’s Substitution Principle  Barbara Liskov – Born 7 November 1939 Barbara Liskov *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 62/128

  32. 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 of type T. Then q(y) should be true for objects y of type S where S is a subtype of T 63/128

  33. 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 64/128

  34. 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 of S (correctness, task, etc.) T P S 65/128

  35. 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 66/128

  36. Polymorphism – Liskov’s Substitution Principle class Rectangle : public Shape { class Square : public Rectangle { private: int w, h; public: public: void set_width(int w) { virtual void set_width(int wi) { Rectangle::set_height(w); w=wi; Rectangle::set_width(w); } } virtual void set_height(int he) { void set_height(int h) { h=he; 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. 67/128

  37. 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 P S 68/128

  38. 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())); } } 69/128

  39. Polymorphism  Class-based, typically Java final SuperClass superClass = new SubClass(); final SubClass subClass = new SubClass(); 70/128

  40. 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())); } } 71/128

  41. Covariance of return type  Objects returned by getSomething Polymorphism in any subclass are always compatible with that expected by the superclass  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())); } } 72/128

  42. 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(); } } 73/128

  43. If contavariance of return type  Objects returned by getSomething Polymorphism in a subclass would not be compatible with that expected by the superclass  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(); } } 74/128

  44. 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())); } } 75/128

  45. Post-conditions in the subtype must Polymorphism be the same as or stronger than in the supertype  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())); } } 76/128

  46. Post-conditions in the subtype must Polymorphism be the same as or stronger than in the supertype  Class-based, typically Java class SuperClass { Object getSomething() { return new Object(); Post-condition } } 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())); } } 77/128

  47. Post-conditions in the subtype must Polymorphism be the same as or stronger than in the supertype  Class-based, typically Java class SuperClass { Object getSomething() { return new Object(); Post-condition } } class SubClass extends SuperClass { Covariance 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())); } } 78/128

  48. 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(""); } } 79/128

  49. Contravariance of arguments types  Objects used by getSomething in Polymorphism any subclass are always narrower to allow calling the super method  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(""); } } 80/128

  50. 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(""); } } 81/128

  51. Covariance of arguments types  Objects used by getSomething in Polymorphism any subclass would confuse the compiler: which method to use?  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(""); } } 82/128

  52. 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(""); } } 83/128

  53. Pre-conditions in the subtype must be Polymorphism the same as or weaker than in the supertype  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(""); } } 84/128

  54. Pre-conditions in the subtype must be Polymorphism the same as or weaker than in the supertype  Class-based, typically Java class SuperClass { void getSomething( final String aParameter) { System. out .println("One implementation..."); Pre-condition } } 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(""); } } 85/128

  55. Pre-conditions in the subtype must be Polymorphism the same as or weaker than in the supertype  Class-based, typically Java class SuperClass { void getSomething( final String aParameter) { System. out .println("One implementation..."); Pre-condition } } class SubClass extends SuperClass { Contravariance 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(""); } } 86/128

  56. Polymorphism  Contra-variance in more depth…  Thank you http://www.jdoodle.com , Firefox Abduction!, and Eclipse compilers 87/128

  57. 88/128

  58. with v1.3 89/128

  59. 90/128

  60. 91/128

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

  62. Not Another implementation… Another implementation… 93/128 https://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29

  63. 94/128

  64. Valid! Valid! 95/128

  65. 96/128

  66. Workaround! 97/128

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

  68. 99/128 Thank you to Willian Flageol for the example

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

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend