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.
