The Programmers Guide To Kotlin - Type
Written by Mike James   
Monday, 06 November 2017
Article Index
The Programmers Guide To Kotlin - Type

Kotlin is a strongly-typed language, but what exactly does this mean?What is "type" and where does it come from? The idea of a type system is something that you can't avoid when using classes and objects and is worth understanding.

Programmer's Guide To Kotlin Second Edition


You can buy it from: Amazon


  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!


Primitive Data Types

Where do data types come from?

When you first start programming, one of the ideas that seems most difficult is that some primitive data types are somehow incompatible. For example, you can't add a string "2" to an Int 2. The reason is, of course, that one is a string and the other an Int, but to the innocent user they both look like the number two.

This is where the idea of data type originates, but it is not where it ends up. 

Primitive data type originates in the different ways that data can be represented. You can represent the idea of "two" either as a String "2", as an Integer 2, or as a float 2.0 and so on. The actual bit patterns used to represent the different incarnations of two are different and the operations you can subject them to vary in difficulty of implementation. You could implement an addition operator for numbers represented as strings, but it is much easier to implement addition using Ints.

Type in this sense is something of a nuisance rather than a help and managing it is a matter of learning how to use functions to perform conversion between the different types so that you can perform operations between them that make sense. 

This can be thought of as "active" type conversion because it involves a change of representation. 

Such active type conversions are generally implemented as conversion functions. For example, the toInt String method will convert a suitable string to an Int:

val myString="1234"
val myNumber=myString.toInt()

Of course, this only works if the String can be parsed as a valid integer. If not the result is an exception. This sort of type conversion is risky, but we usually cannot avoid it. 

Kotlin Strings have a range of type conversion functions and so do the other primitive types. 

Notice that you cannot use a Java/C++ style cast to convert types in Kotlin. That is:

val myNumber:Int=(Int) myString

doesn't mean anything in Kotlin. 

The Class Type Hierarchy

When you move beyond primitive types things become more interesting.

Each class that you create can be used to create multiple instances. This is exactly the same as creating multiple instances of an Int or a String, and these are regarded as different data types. It seems natural to extend the idea so that each class you define is a new data type. In this case, however, the term doesn't really relate to how the data is represented or stored. It has more to do with what instances of the class can do i.e. what properties and methods they have. 

As a class that inherits from another class may be the base class for another class, we slowly build up a class hierarchy. All classes start off by inheriting the default Any class, more of which later. The result is that classes form a family tree that starts off from Any and branches out as each new class inherits from the previous classes. 




As a class that inherits from another class generally adds properties and methods, you can think of the new derived class as being in some sense “bigger” than the base class. When you define a new class it always has a relationship to the classes it inherits from. At its simplest this could be just Any, which is the root of the inheritance hierarchy. In many cases a class will also have a relationship with classes that have been derived from it. 

For example:

open class MyClassA{
    fun myFunctionA(){}

class MyClassB:MyClassA() {
fun myFunctionB(){}

then ClassB has all of the methods and properties of ClassA plus some of its own.

Thus ClassB is “bigger” than ClassA because it contains at least all of ClassA.


What this means is that you can treat a ClassB object as if it was in fact a ClassA object. In this case you would be ignoring the new members added by defining ClassB by simply restricting your access to ClassA methods and properties. This “downsizing” of ClassB is generally called an upcast because it moves you up the object hierarchy towards the root object.






Last Updated ( Monday, 06 November 2017 )