Object-Oriented Programming - Subtype Polymorphism Lecture Notes PDF

Document Details

PromisingSavannah1642

Uploaded by PromisingSavannah1642

České vysoké učení technické v Praze

Filip Křikava

Tags

object-oriented programming subtype polymorphism scala computer science

Summary

These lecture notes cover object-oriented programming concepts, specifically subtype polymorphism. Examples in Scala are provided, demonstrating the creation and use of subtypes.

Full Transcript

Object-Oriented Programming 2. Subtype Polymorphism Filip Křikava https://courses.fit.cvut.cz/BI-OOP/ 1 Any questions? 2 Don't forget - Today is the practice quiz! 3 What is a...

Object-Oriented Programming 2. Subtype Polymorphism Filip Křikava https://courses.fit.cvut.cz/BI-OOP/ 1 Any questions? 2 Don't forget - Today is the practice quiz! 3 What is an object? - An object is a structure with a state, behavior and identity - state - instance variables (fields) - behavior - (instance) methods that alone are capable of accessing the object state - recursive - they can refer to themselves Don't forget identity! - In the class-based system, it is a runtime instance of some class - Objects communicate with one another by message passing - in the mainstream OOP sending a message is essentially a method invocation - In this course we will assume reference semantics - all objects are implicitly references - this is the case of Java, Scala, Kotlin, JavaScript, Python, and other managed languages 4 What is a class? - A blueprint (a template) for creating objects - possibly extensible - defines object's runtime structure - defines class members (fields, methods, constructors) - Provide initial values for its state and implementation of its behavior - all objects created from the same class share the same methods, but contain separate copies of their instance variables (fields) - In class-based languages it defines a type - in statically-typed languages it is a compile-time type - In this course we will focus primarily on class-based languages 5 https://scastie.scala-lang.org/8N7nU7KNSMCAchuRw79bxg Example - a class definition class Counter(init: Int = 0, val increment: Int = 1): private var cnt: Int = 0 - Creates a new class called Counter with 6 members: - 1 constructor with 2 parameters - init with default value 0 this.set(init) def get: Int = { - increment with default value 1 this.cnt } - 2 instance variables (properties/fields) def set(x: Int): Unit = { - increment - immutable publicly accessible assert(x >= 0, "Negative counter value") - cnt - mutable accessible only from within the Counter class this.cnt = x } - 3 methods def inc(): Unit = { this.cnt += this.increment - get - parameterless method (getter) - set - one parameter method (setter) } - inc - parameterless method val c = Counter(init = 1) c.inc() - the extra () emphasize that this method assert(c.get == 2) c.inc() does a side-effect - modifying the internal assert(c.get == 3) state of the object assert(c.increment == 1) 6 https://scastie.scala-lang.org/deNLX5XGTkGRqjsRDd0zpA Example - subclassing / inheritance class Counter { class DoublingCounter extends Counter { Counter var x: Int = 1 var backup: Int = x + x: Int def get: Int = { override def get: Int = { this.x this.backup = this.x } this.x + get(): Int } + inc(): Unit def inc(): Unit = { this.x += 1 def reset(): Unit = { } this.x = this.backup } } override def inc(): Unit = { DoublingCounter super.inc(); super.inc() } UML class diagram.. + backup: Int } UML is language agnostic, thus parens + get(): Int - A subclass is a differential description of a class for all methods + reset(): Unit + inc(): Unit - The subclass relation is the partial order induced by the subclass declarations - The subclass inherits members of its superclass 7 https://scastie.scala-lang.org/deNLX5XGTkGRqjsRDd0zpA Example - subclassing / inheritance class Counter { class DoublingCounter extends Counter { val c = DoublingCounter() var x: Int = 1 var backup: Int = x c.inc() println(c.get) // 3 def get: Int = { override def get: Int = { c.inc() this.x this.backup = this.x c.reset() } this.x println(c.get) // 3 } def inc(): Unit = { this.x += 1 def reset(): Unit = { } this.x = this.backup } } override def inc(): Unit = { super.inc(); super.inc() } } - A subclass is a differential description of a class - Subclassing creates subtyping relation a partial order induced by the subclass declarations - The subclass inherits all non-private/non-overridden members of its superclass 8 https://scastie.scala-lang.org/a2D5lgcNRAyLxzUDKHBrqA Example - subclassing / inheritance - The meaning of this is dynamic - I can only be sure who to call at runtime - The meaning of super is static - I always know who to call in the class after extends class Counter { class DoublingCounter extends Counter { val c: Counter = var x: Int = 1 var backup: Int = x DoublingCounter() def get: Int = { override def get: Int = { c.inc() this.x this.backup = this.x println(c.get) // 3 } this.x c.inc2() def inc(): Unit = { } println(c.get) // ??? this.x += 1 } def reset(): Unit = { def inc2(): Unit = { this.x = this.backup this.inc(); this.inc() } } } override def inc(): Unit = { super.inc(); super.inc() } } https://scastie.scala-lang.org/2fkJpDvjR4iGWuhjWrImxg Example - subtyping and dynamic dispatch A function expecting an object def inc3(c: Counter): Unit = { compatible with a Counter c.inc(); c.inc(); c.inc() } Dynamic dispatch val c = DoublingCounter() A new instance of DoublingCounter inc3(c) Subtyping allows us to pass c.get // returns ??? instance of DoublingCounter where just a Counter is expected - The dynamic dispatch is the process of selecting which implementation will be called at runtime - Instances of different classes may be used interchangeably as long as they have compatible type - What is compatible type is given by the notion of subtyping - For now, we focus on single dispatch where we consider only the type of the method receiver (left side of the. operator) 10 Example - removing type annotation and explicit reference to this 11 class Counter { class Counter { var x: Int = 1 var x = 1 def get: Int = this.x def get = x def inc(): Unit = { def inc() = x += 1 this.x += 1 } } } class ResetCounter extends Counter { override def inc() = { class ResetCounter extends Counter { super.inc() override def inc(): Unit = { super.inc() super.inc() } super.inc() def reset() = x = 1 } } def reset(): Unit = { this.x = 1 - Scala uses type inference - it can infer most of the types (except } } parameter types, return types in recursive functions) - Comes at a price - reduced syntactic noise vs reduced information - A good practice is to keep type annotation in public API - public instance variables / methods Subtype Polymorphism 12 Intermezzo (λ x. e1 ) e2 13 Intermezzo (λ x:{a:ℤ}. x.a) {a=1} Application rule 14 Intermezzo Subtyping relation S is a subtype of T (λ x:{a:ℤ}. x.a) {a=1,b=2} Application rule Subsumption rule 15 Polymorphism - The many forms in our context means roughly same interface, different underlying data types - Subtype polymorphism - allows a function to take an object of a some type T, but also work correctly, if called with an object of a type S that is a subtype of T - Parametric polymorphism - allows a function or a data type to be written generically, so that it can handle values uniformly without depending on their type - Ad-hoc polymorphism - allows a function to be applied to arguments of different types, but behave differently depending on the type of the argument to which they are applied 16 Subtype polymorphism - A form of type polymorphism - A relation between two types by some notion of substitutability If A is a subtype of B, the subtyping relation Subtyping is relation that is - transitive A

Use Quizgecko on...
Browser
Browser