Kotlinlearncs.online LogoJava

    ← Prev

    Index

    Next →

    Kotlin
    Java
    • Equality and Object Copying : 32

    • Polymorphism : 31

    • Inheritance : 30

    • Data Modeling 1 : 29

    • Companion Objects : 28

    • Encapsulation : 27

    • Constructors : 26

    • Objects, Continued : 25

    • Introduction to Objects : 24

    • Compilation and Immutability : 23

    • Practice with Collections : 22

    • Maps and Sets : 21

    • Lists and Type Parameters : 20

    • Imports and Libraries : 19

    • Multidimensional Arrays : 18

    • Practice with Strings : 17

    • null : 16

    • Algorithms and Strings : 15

    • Strings : 14

    • Functions and Algorithms : 13

    • Practice with Functions : 12

    • More About Functions : 11

    • Errors and Debugging : 10

    • Functions : 9

    • Practice with Loops and Algorithms : 8

    • Algorithms I : 7

    • Loops : 6

    • Arrays : 5

    • Compound Conditionals : 4

    • Conditional Expressions and Statements : 3

    • Operations on Variables : 2

    • Variables and Types : 1

    • Hello, world! : 0

    Polymorphism

    open class Pet {
    fun speak() {
    println("I'm a pet")
    }
    }
    class Dog : Pet() {
    fun woof() {
    println("I'm a dog!")
    }
    }
    class Cat : Pet() {
    fun meow() {
    println("I'm a cat!")
    }
    }
    fun speak(pet: Pet) {
    when (pet) {
    is Dog -> pet.woof()
    is Cat -> pet.meow()
    else -> pet.speak()
    }
    }
    val xyz = Cat()
    val chuchu = Dog()

    Next we’ll continue to practice with inheritance. We’ll also introduce a new big (literally) idea—polymorphism. Polymorphism may sound scary, but it’s not, and we’ll work it out together like we always do, using a lot of examples.

    Another Puzzle
    Another Puzzle

    Let’s look at another example of puzzling Kotlin code together:

    fun printIt(it: Any) {
    println("OK, I'll print it! $it")
    }
    class Pet
    class Course
    val string = "A String"
    val pet = Pet()
    val course = Course()
    printIt(string)
    printIt(pet)
    printIt(course)

    Polymorphism
    Polymorphism

    Polymorphism is a big word, and sounds a bit scary. But it’s actually quite straightforward. Let’s work it out together starting with the Wikipedia definition:

    In programming languages and type theory, polymorphism is the provision of a single interface to entities of different types

    “Is A”
    “Is A”

    One way to think about polymorphism and Kotlin inheritance is to consider “is a” relationships. For example, every instance of any Kotlin class “is a” Any, because every class is a subclass of Any. Other “is a” relationships depend on inheritance relationships established when classes are declared.

    // Pet is an Any
    open class Pet
    // Dog is a Pet
    // Dog is an Any
    open class Dog : Pet()
    // Mutt is a Dog
    // Mutt is a Pet
    // Mutt is an Any
    class Mutt : Dog()

    Method Overriding and Polymorphism
    Method Overriding and Polymorphism

    One frequent confusion regarding polymorphism has to do with overriding inherited methods. Let’s look at how that works:

    open class Pet {
    open fun getType(): String {
    return "Pet"
    }
    }
    class Dog : Pet() {
    override fun getType(): String {
    return "Dog"
    }
    }
    class Cat : Pet()
    fun greetPet(pet: Pet) {
    println("Hello ${pet.getType()}")
    }
    val dog = Dog()
    val cat = Cat()
    greetPet(dog)
    greetPet(cat)

    Up and Down Casting
    Up and Down Casting

    When we create an instance of a class, we can save it into a variable of any type that it can morph into:

    open class Pet
    class Dog : Pet()
    val dog: Dog = Dog()
    val pet: Pet = Dog()
    val any: Any = Dog()

    This is referred to as upcasting. Kotlin will automatically upcast an instance to any of its supertypes. Because Dog extends Pet and Pet extends Any, a Dog can be stored in a Dog, Pet, or Object variable.

    One thing to note above is that we needed to specify the type of our variables explicitly. If we simply allow Kotlin to perform type inference, each variable above would be of type Dog, since Kotlin will infer the type of the variable to be the type that it is first used to store.

    However! The type of the variable determines what we can do with that object. Let’s look at how.

    open class Pet
    class Dog : Pet()
    val dog: Dog = Dog()
    val pet: Pet = Dog()
    val any: Any = Dog()

    Don’t worry if this seems a bit fuzzy now. We’ll return to this topic a few lessons from now when we discuss object references.

    Down Casting and Flow Typing
    Down Casting and Flow Typing

    Consider the type hierarchy established below: Given a Pet variable, it might refer to a Dog, a Cat, a Pet or some other kind of pet!

    open class Pet
    class Dog : Pet() {
    fun bark() { }
    }
    class Cat : Pet() {
    fun meow() { }
    }
    val dog = Dog()
    val cat = Cat()
    val pet = Pet()

    Is there a way that we can tell? Yup! To test if an object is an instance of a particular class, we use the is operator. And, better yet, once we test a type using is Kotlin will automatically allow us to use the methods declared on that class through a process called flow typing. Let’s examine how that works:

    open class Pet
    class Dog : Pet() {
    fun bark() { }
    }
    class Cat : Pet() {
    fun meow() { }
    }
    val dog = Dog()
    val cat = Cat()
    val pet = Pet()

    Practice: Polymorphic Greeter

    Created By: Geoffrey Challen
    / Version: 2020.9.0

    Write a method name greet that accepts a nullable Person as an argument and returns a String or null.

    Depending on what kind of person it is, you should greet them differently:

    • If the person is a Professor—for instance, one named "Geoff"—you should greet them "Hi Professor Geoff"
    • If the person is a Student—for instance, one named "Friendly"—you should greet them "Hey Friendly, you are not alone!"
    • If the person is a Staff, then they will have a String role you can retrieve using getRole. For example, if their role is "advising" their name is "Chuchu", you should greet them "Thanks Chuchu for all your help with advising".

    All Persons have a name property. If the person is null or not one of the kinds of people described above, return null. Do not solve this problem using method overloading. And do not hard-code the answers. Your solution should work for any Professor, Student, or Staff.

    Steady There
    Steady There

    The last two lessons have been pretty loaded with new ideas and concepts! Exciting, but also enough to make your head spin.

    Don’t worry. Over the next two lessons we’ll slow down and review what we’ve learned. And then, over the lessons that follow we’ll have even more opportunities to integrate this knowledge, but with a small twist. So be patient. This won’t all make sense immediately. But it will all make sense eventually.

    Homework: Polymorphic Orderer

    Created By: Geoffrey Challen
    / Version: 2021.9.0

    Create a method named order. order should accept a single parameter, a Restaurant? to order from, and return a String, a comment on your order. Depending on which subclass of Restaurant it is, you should respond differently:

    • If the restaurant is a Fancy restaurant—for instance, with name "MIGA"—you should order "At MIGA I'll order something inexpensive"
    • If the restaurant is a FastFood restaurant, for instance, with with name "Chipotle"—you should order "At Chipotle I'll order something healthy"
    • If the restaurant is a Vegan restaurant, then it will have a String property cuisine you can retrieve using getCuisine. For example, if it its cuisine is "Thai" and name is "Vegan Delight", you should order "At Vegan Delight I'll order delicious Thai food".

    All Restaurants have a name that you can retrieve as the property name. If the restaurant is null or not one of the kinds described above, return null. Do not solve this problem using method overloading. And do not hard-code the answers. Your solution should work for any Fancy, FastFood, or Vegan instance.

    Note that we are not implying that there are not fancy vegan restaurants or fancy fast food restaurants or vegan fast-food restaurants. If anything, the ability of real entities to resist strict classification is one of the limitations of Kotlin's object model.

    More Practice

    Need more practice? Head over to the practice page.