Kotlin Interfaces

Interfaces in Kotlin.

fun main() {
    println(InheritingClass("A name").number2)
}

// Very similar in implementation to Java

interface MyInterface { // No primary constructor () as you never make an instance. Open not required, as extendable by default
    val number: Int // Can include properties in interfaces. This variable is currently abstract
//    val number2: Int = 50 // Initialising properties not allowed in interfaces. Instead:
    val number2: Int
        get() = 50 // Declare getter to return fixed value. However, no 'field' available here.
    fun myFunction(str: String): String
}

interface MySubInterface: MyInterface {
    fun mySubfunction(num: Int): String
}

class anotherSomething(override val number: Int) : MySubInterface { // Implement abstract property
    override fun myFunction(str: String): String {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun mySubfunction(num: Int): String {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

}

// A class can extend from another class and implement and interface at the same time:
open abstract class AbstractClass(val name: String) {
    open fun printName() = println("The name is $name")
    abstract fun aNumber(): Double
}

class InheritingClass(name: String): AbstractClass(name), MyInterface { // both inherits and implements interface
    override val number: Int = 5 // Implement abstract property
    override fun myFunction(str: String): String {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun aNumber(): Double {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
}

 

Kotlin Inheritance

Inheritance in Kotlin.

fun main() {
    val laserPrinter = LaserPrinter("Brother 1234", 15)
    laserPrinter.printModel()
    SomethingElse("Hey")
}

open abstract class Printer(val modelName: String) { // Must be declared open as everything is final by default, therefore not extendable. Abstract in this case, which makes 'open' declaration redundant. () added to create primary constructor
    open fun printModel() = println("The model of this printer is $modelName") // Must be open to be overridden
    abstract fun bestSellingPrice(): Double // Does not need to be declared open as is abstract
}

open class LaserPrinter(modelName: String, ppm: Int): Printer(modelName) { // To extend a class in Kotlin use the : annotation. Requires Printer to be initialised as Printer has constructor by default, so () added after both LaserPrinter and Printer
    // We do not have to match constructor signatures (see ppm added in LaserPrinter not present in Printer)
//    constructor(): super() // How to initialise the Printer class if we don't want a primary constructor in Printer i.e. it doesn't have () in the first line
    final override fun printModel() = println("The model of this laser printer is $modelName") // Overrides the super implementation. Final has been added to prevent further overriding

    override fun bestSellingPrice(): Double = 129.99 // Pretend this is an actual function that does something. Still need to use override for abstract functions
    // When a function is overridden it is declared open, therefore can be overridden by subclasses. If not desirable,

}

class specialLaserPrinter(modelName: String, ppm: Int): LaserPrinter(modelName, ppm) { // LaserPrinter needs to be open to subclass
    override fun bestSellingPrice(): Double { // bestSellingPrice can be overridden
        return super.bestSellingPrice() + 5
    }
//    override fun printModel() // Won't work because printModel() is final in LaserPrinter
}


// Secondary constructors (which can take a function where the primary cannot) in inherited classes only make sense if no primary constructor is called, as so:
open class Something { // No primary constructor
    val someProperty: String

    constructor(someParameter: String) {
        someProperty = someParameter
        println("I'm in the parent's constructor")
    }
}

class SomethingElse: Something { // No primary constructor

    constructor(someOtherParameter: String): super(someOtherParameter) {
        println("I'm in the child's constructor")
    }
}

//open data class DataClass(val number: Int) {} // Data classes are closed-typed cannot extended, abstract or inner classes. Can inherit FROM other classes, but stops there.