The Programmers Guide To Kotlin - Inheritance
Written by Mike James   
Monday, 07 August 2017
Article Index
The Programmers Guide To Kotlin - Inheritance
Interfaces
Delegation

Delegation

As if classes, interfaces and abstract classes weren't enough ways to handle inheritance Koltin also supports delegation. 

Delegation in its most general form simply means creating an instance of a class within another class and then using its methods to implement the containing class's methods. This is supposed to be a safer form of "inheritance" and you will hear the saying "prefer composition to inheritance". Composition is where one object acquires the methods of another by simply containing an instance of the object. Calls to the methods of the contained object are simply passed onto it by the containing object - a sort of delegation.

This is simple and direct but manually creating all of the methods needed redirect calls to the object that does all of the work is tedious and error prone. 

For example suppose we have an Printer class that prints some messages. We could use inheritance to give a derived class the same methods. Alternatively we could achieve the same result by creating an instance of the Printer class within our derived class. That is given the class:

class Printer{
    fun myFunc(mess: String) {       
       println(mess)
    }
}

You can use manual delegation to implement a "derived" class which has the same myFunc method implemented by the existing Printer class quite simply:

class MyClass{
 var printerObject=Printer()
 fun myFunc(mess:String){
      printerObject.myFunc(mess)
 }
}

You can see that we have created an instance of the Printer class and then used it to implement the new myFunc method.

This is delegation in action and it is simple but if there are very many methods to delegate very tedious.

Kotlin will do automatic delegation for you but there are some limitations.

The first is that you have to have an interface defined that specifies all of the methods that are going to be delegated. Next you have to have an object that implements the interface. You can get an object that implements the interface either by creating a class that implements the interface and then creating and instance or directly creating an object. Once you have the object the derived class can delegate all of the interface methods to the object using the keyword by.

For example to delegate the Printer methods as before we would first define an interface that specifies the methods to be automatically delegated:

interface Iprinter{
    fun myFunc(mess:String)
}

There is just one method in this case but in general there will be a list of virtual and implemented methods. Next we have to create an object that implements these methods:

object printer:Iprinter{
     override fun myFunc(mess: String) {
        println(mess)
    }
}

Now we can create a "derived" class that delegates all of the calls to the methods in the interface to the object that implements the interface:

class MyClassA:Iprinter by printer{
    }

You can now create an instance of MyClassA and call the myFunc method which is implemented automatically by the system as a call to printer.myFunc(mess).

As already stated you could create a Printer class that implemented the Iprinter interface and then use an instance as the object that is delegated to. Also notice that while the body of the derived class is emtpy in this example you can override the delegated methods and provide a new implementation. 

At first sight automatic delegation seems like a powerful feature but the need to define an interface and then implement it makes it less so. Manual delegation can take any object and use it to create a derived class by delegation even if the "base" class is final and cannot be used by inheritance. However automatic delegation needs the "base" class to implement the interface of methods to be delegated. What this means is that the base class has to be prepared for delegation just as much as for inheritance.

Notice that in inheritance a class inherits from another class but in delegation a class inherits from an object.  

Visibility Modifiers, Packages and Modules

In the introduction it was explained that the way to tame inheritance is to control access to the inner workings of a class. If the outside world can only make use of what the class does and not how it does it then changes to the base class that doesn't alter what it does should be safe. 

To control access to classes and class members Kotlin has four visibility modifiers and while their meanings depend on context their intent is clear: 

  • public - visible everywhere

  • private - only visible inside the containing unit

  • protected - same as private but also visible to sub classes

  • internal - visible to any other code in the same module

When applied to the members of a class or interface these have obvious meanings. Public means that the method or property is accessible and private means they aren't. Notice that the inner workings of a method aren't accessible outside of a class even if declared public. This is a special case of the more general rule that local variables are always inaccessible.

Also notice that an outer class doesn't see the private members of an inner class.

You can also apply visibility modifiers to constructors.

Kotlin also uses the idea of a package and a module to control access.  Packages work roughly the same way that they do in Java. A source file can declare itself a member of a package using:

package mypackage.myname

following this the fully qualified name of any class or function has mypackage.myname prefixed e.g. mypackage.myname.MyClass. 

In other languages a package would be called a namespace. 

If another source file wants to use something from another package it has to import it.

import mypackage.myname.MyClass

and to import everything in the package you can use a wild card:

import mypackage.myname.*

A class can also be assigned an alias to resolve name clashes -

import mypackage.myname.MyClass as AnotherClass

Any private properties or functions declared at the top level of a package i.e. not within a class are visible thoughout the package but not outside of the package. 

Kotlin has one other level of organization - the module. This is more like a compiler unit rather than something abstract. A module is 

  • an IntelliJ IDEA module;
  • a Maven project;
  • a Gradle source set;
  • a set of files compiled with one invocation of the Ant task 

Anything marked as internal in a package is visible everywhere within the module. This is most probably best avoided if possible.  

                                                                                                                                                                                                                 

 

Programmer's Guide To Kotlin Second Edition

kotlin2e360

You can buy it from: Amazon

Contents

  1. What makes Kotlin Special
  2. The Basics:Variables,Primitive Types and Functions 
  3. Control
         Extract: If and When 
  4. Strings and Arrays
  5. The Class & The Object
  6. Inheritance
  7. The Type Hierarchy
  8. Generics
  9. Collections, Iterators, Sequences & Ranges
        Extract: Iterators & Sequences 
  10. Advanced functions 
  11. Anonymous, Lamdas & Inline Functions
  12. Data classes, enums and destructuring
        Extract: Destructuring 
  13. Exceptions, Annotations & Reflection
  14. Coroutines
        Extract: Coroutines 
  15. Working with Java
        Extract: Using Swing ***NEW!

<ASIN:B096MZY7JM>

kotlinlogo

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

 

Banner


Quadrupedal Parkour
31/03/2024

What is it with robots and parkour? First Atlas and now ANYmal want to impress us with their prowess. For the roboticist, however, emulating the skills of free running can enhance the capabilities of  [ ... ]



Java Version 22 Released
04/04/2024

JDK 22 is not a Long Term Support release, but is one of the regular releases that are scheduled to arrive every six months. Still, it has got a lot to show for itself.


More News

raspberry pi books

 

Comments




or email your comment to: comments@i-programmer.info

 <ASIN:1871962536>



Last Updated ( Sunday, 10 September 2017 )