Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

Agenda ● Object-Oriented Introduction ● Kotlin and OOP ● SOLID Principles

Slide 3

Slide 3 text

What is Object Oriented Programming (OOP)? ● A programming paradigm ○ “Everything is an object” ● Smalltalk (around 1970) ● “Real-World” modeling and programming ● Introduces ○ Abstraction ○ Encapsulation ○ Inheritance ○ Polymorphism

Slide 4

Slide 4 text

Why OOP ● It’s well known and accepted ● Allows for state organization ● Flow of control through interfaces and abstractions

Slide 5

Slide 5 text

Flow Of Control Main Function High-Level Modules High-Level Modules Low-Level Modules Low-Level Modules Low-Level Modules Low-Level Modules

Slide 6

Slide 6 text

Main Function High-Level Modules High-Level Modules Low-Level Modules Low-Level Modules Low-Level Modules Low-Level Modules Flow Of Control With Abstractions High-Level Interface High-Level Interface Low-Level Interface Low-Level Interface Low-Level Interface Low-Level Interface

Slide 7

Slide 7 text

Agenda ● Object-Oriented Introduction ● Kotlin and OOP ● SOLID Principles

Slide 8

Slide 8 text

Kotlin and OOP ● Everything is an object ● Primitives are boxed at compile time ● Classes are derived from Any (Or Any?) ● Not covered in this session ○ Nullable classes are derived from Any? ○ Nothing is also something but it’s not Any ○ Generics

Slide 9

Slide 9 text

Kotlin and OOP - Basics ● Classes class Person(val firstName: String, val lastName: String) { fun fullName(): String = "$firstName $lastName" } interface Person { val age: Int fun fullName(): String } abstract class Person(val firstName: String, val lastName: String) { abstract fun fullName(): String } ● Interfaces ● Abstract Classes

Slide 10

Slide 10 text

Kotlin and OOP - Basics ● Enum Classes enum class Person { ALEX { override fun sayName() = "Alex" }, DOR { override fun sayName() = "Dor" }, IGOR { override fun sayName() = "Igor" }; abstract fun sayName(): String }

Slide 11

Slide 11 text

Kotlin and OOP - Inheritance ● A class may only extend one class ● A class may implement many interfaces ● An interface may extend other interfaces ● To do all of this - use a colon (:)

Slide 12

Slide 12 text

Inheritance Example interface Person { fun fullName(): String } abstract class Bob(open val firstName: String): Person { abstract fun fullName(): String //can be omitted fun sayName(): String = "My Name Is $firstName" }

Slide 13

Slide 13 text

Inheritance Example - Continued class BobDylan: Bob("Bob") { override fun fullName(): String = "${sayName()} Dylan" } class BobDole(override val firstName: String = "Bob", val lastName: String = "Dole"): Bob(firstName) { override fun fullName(): String = "I'm Bob Dole" } abstract class Bob(open val firstName: String): Person { abstract fun fullName(): String //can be omitted (from person) fun sayName(): String = "My Name Is $firstName" }

Slide 14

Slide 14 text

Kotlin and OOP - Not So Basic ● Data Classes ● Sealed Classes ● Smart Casting

Slide 15

Slide 15 text

Data Classes data class Elvis(val firstName: String = "Elvis", val lastName: String = "Presley") open data class Elvis(val firstName: String = "Elvis", val lastName: String = "Presley") Compiler will complain!

Slide 16

Slide 16 text

Sealed Classes sealed class Person(val firstName: String, val lastName: String) { class Dor: Person("Dor", "Samet") class Alex(val age: Int, fName: String, lName: String) : Person(fName, lName) }

Slide 17

Slide 17 text

Sealed Classes - Since Kotlin 1.1 sealed class Person(val firstName: String, val lastName: String) class Dor: Person("Dor", "Samet") data class Alex(val age: Int, fName: String, lName: String) : Person(fName, lName)

Slide 18

Slide 18 text

Smart Casting fun translatePerson(person: Person): String = when (person) { is Person.Dor -> { "${person.firstName} ${person.lastName}" } is Person.Alex -> { "${person.fName} ${person.lName}, of age ${person.age}" } }

Slide 19

Slide 19 text

Questions

Slide 20

Slide 20 text

Agenda ● Object-Oriented Introduction ● Kotlin and OOP ● SOLID Principles

Slide 21

Slide 21 text

SOLID Principles SRP - Single Responsibility Principle OCP - Open/Closed Principle LSP - Liskov Substitution Principle ISP - Interface Segregation Principle DIP - Dependency Inversion Principle

Slide 22

Slide 22 text

SOLID Kotlin Language Features SRP - Single Responsibility Principle - “by” keyword which will get its own talk OCP - Open/Closed Principle LSP - Liskov Substitution Principle ISP - Interface Segregation Principle DIP - Dependency Inversion Principle - named and default parameters

Slide 23

Slide 23 text

Open/Closed Principle “I am open to extensions and closed to modifications”

Slide 24

Slide 24 text

Open/Closed Principle Open/Override ● Classes are final by default ● Must explicitly write “open” for extendable classes and methods ● Must explicitly write “override” for extending classes and methods

Slide 25

Slide 25 text

Open/Closed Principle Example open class Developer(val language: String) { open fun writeCode() = "I Write code in $language" } open class JavaDeveloper(otherLanguage: String) : Developer(otherLanguage) { open val version = "9" constructor(): this("Java") //Secondary Constructor override fun writeCode(): String = writeJavaCode() protected open fun writeJavaCode() = "public static void main(String[] args)" } class KotlinDeveloper: JavaDeveloper("Kotlin") { override val version: String = "1.1" override fun writeJavaCode(): String = writeKotlinCode() private fun writeKotlinCode(): String = "fun main(args: Array)" }

Slide 26

Slide 26 text

Open/Closed Principle Example fun main(args: Array) { val developerA = JavaDeveloper() val developerB = KotlinDeveloper() developerA.writeCode() // “public static void main(String[] args)” developerB.writeCode() // “fun main(args: Array)” }

Slide 27

Slide 27 text

Liskov Substitution Principle “Replacing me with my parent should not break the system”

Slide 28

Slide 28 text

Liskov Substitution Principle Type Inference ● Built-in type inference ● Exchanging between items using type inference is not even a line ● Sealed classes ● When expressions ● Smart casting

Slide 29

Slide 29 text

Type Inference - Revisited fun main(args: Array) { val developerA = JavaDeveloper() // JavaDeveloper -> Developer val developerB = KotlinDeveloper() // KotlinDeveloper -> Developer developerA.writeCode() developerB.writeCode() } Can we do better?

Slide 30

Slide 30 text

Liskov Substitution Principle Example fun generateDeveloper(language: String): Developer = when(language) { "Java" -> JavaDeveloper() "Kotlin" -> KotlinDeveloper() else -> Developer(language) } fun doWork(developer: Developer) { developer.writeCode() }

Slide 31

Slide 31 text

Liskov Substitution Principle Example fun main(args: Array) { val developer = generateDeveloper("Java") doWork(developer) }

Slide 32

Slide 32 text

Liskov Substitution Principle Example fun main(args: Array) { val developer = generateDeveloper("Kotlin") doWork(developer) }

Slide 33

Slide 33 text

Liskov Substitution Principle Example fun main(args: Array) { val developer = generateDeveloper("Python") doWork(developer) }

Slide 34

Slide 34 text

Interface Segregation Principle “I should not be forced to implement methods I do not need”

Slide 35

Slide 35 text

Interface Segregation Principle Interfaces are basically abstract classes with all abstract methods ● A class may implement multiple interfaces ● Interfaces may have default implementations of functions ● Interfaces may have members

Slide 36

Slide 36 text

Interface Segregation Principle Example interface JavaProgrammer { fun writeJavaCode(): String } interface KotlinProgrammer { fun writeKotlinCode(): String }

Slide 37

Slide 37 text

Interface Segregation Principle Example open class JavaDeveloper(otherLanguage: String) : Developer(otherLanguage), JavaProgrammer { open val version = "9" constructor(): this("Java") override fun writeCode(): String = writeJavaCode() override fun writeJavaCode() = "public static void main(String[] args)" }

Slide 38

Slide 38 text

Interface Segregation Principle Example class KotlinDeveloper: JavaDeveloper("Kotlin"), KotlinProgrammer { override val version: String = "1.1" override fun writeJavaCode(): String = writeKotlinCode() override fun writeKotlinCode(): String = "fun main(args: Array)" }

Slide 39

Slide 39 text

Interface Segregation Principle Example class KotlinDeveloper: Developer("Kotlin"), KotlinProgrammer { override val version: String = "1.1" override fun writeKotlinCode(): String = "fun main(args: Array)" }

Slide 40

Slide 40 text

Questions

Slide 41

Slide 41 text

Thank You