Kotlin Tutoial

Basics

Control Flow

Array & String

Functions

Collections

OOPs Concept

Exception Handling

Null Safety

Regex & Ranges

Java Interoperability

Miscellaneous

Android

Kotlin Interfaces

Interfaces in Kotlin are a way to define a contract that classes must adhere to. They can contain declarations of abstract methods and can also provide implementations for some methods. This tutorial will walk you through Kotlin interfaces and their features.

1. Basic Interfaces:

In Kotlin, you can declare an interface using the interface keyword.

interface Drivable {
    fun drive()
}

2. Implementing an Interface:

Once an interface is declared, a class can implement it using the : symbol.

class Car : Drivable {
    override fun drive() {
        println("Driving a car!")
    }
}

3. Properties in Interfaces:

Kotlin allows you to declare properties in interfaces, but you need to provide either an implementation or ensure that implementing classes define it.

interface NamedEntity {
    val name: String
}

class Person(override val name: String) : NamedEntity

4. Default Implementations:

Kotlin interfaces can provide default implementations of methods.

interface Walker {
    fun walk() {
        println("Walking!")
    }
}

class Human : Walker  // No need to override `walk` unless a different implementation is desired.

5. Implementing Multiple Interfaces:

A class can implement multiple interfaces. If there's a method name clash, you'll have to provide a manual override.

interface Flyable {
    fun move() {
        println("Flying!")
    }
}

interface Swimable {
    fun move() {
        println("Swimming!")
    }
}

class Duck : Flyable, Swimable {
    override fun move() {
        println("Duck can both fly and swim!")
    }
}

6. Interfaces and Interoperability:

Since Kotlin compiles down to JVM bytecode, its interfaces are compatible with Java. However, some features, like default implementations, might need additional consideration when interfacing with Java code.

7. Evolution of Interfaces:

In Kotlin, if you want to add a new method to an interface and provide a default implementation for it, you can do so without breaking existing implementations. This is in contrast to Java, where before Java 8, adding a new method to an interface would break all existing implementations.

8. Restrictions:

  • Interfaces cannot store a state (i.e., cannot have backing fields for properties).
  • An interface can't have constructors.

9. fun vs val/var in Interfaces:

In an interface, functions (fun) define methods that can have default implementations or can be abstract. On the other hand, properties (val/var) represent abstract properties that must be overridden in implementing classes, unless a getter implementation is provided in the interface.

Conclusion:

Interfaces in Kotlin are a powerful way to abstract out common behavior across multiple classes. They bring in added flexibility by allowing default implementations and are designed to be easily extensible without breaking existing code. Utilizing interfaces effectively can help you craft more modular and maintainable Kotlin applications.

  1. Default methods in Kotlin interfaces:

    • Declare default methods in interfaces to provide a default implementation.
    interface Greetable {
        fun greet(): String
    
        fun defaultGreeting(): String {
            return "Hello, Default!"
        }
    }
    
  2. Properties in Kotlin interfaces:

    • Include properties in interfaces, with or without default values.
    interface Nameable {
        val name: String
    
        val defaultName: String
            get() = "DefaultName"
    }
    
  3. Implementing multiple interfaces in Kotlin:

    • A class can implement multiple interfaces, inheriting their functionalities.
    class MyClass : Greetable, Nameable {
        override fun greet() = "Hello, World!"
        override val name = "MyClass"
    }
    
  4. Interfaces vs abstract classes in Kotlin:

    • Choose between interfaces and abstract classes based on your design needs.
    interface Printable {
        fun print()
    }
    
    abstract class Shape {
        abstract fun draw()
    }
    
  5. Extending interfaces in Kotlin:

    • Extend interfaces to create new ones or combine existing ones.
    interface Drawable : Greetable, Nameable {
        fun draw(): String
    }
    
  6. Interfaces and inheritance hierarchy in Kotlin:

    • Build a hierarchy of interfaces to model complex behaviors.
    interface Flying : Greetable {
        fun fly(): String
    }
    
    class Bird : Flying {
        override fun greet() = "Hello from Bird!"
        override fun fly() = "Bird is flying"
    }
    
  7. Companion objects in Kotlin interfaces:

    • Include companion objects in interfaces for shared functionality.
    interface Loggable {
        companion object {
            fun log(message: String) {
                println("Log: $message")
            }
        }
    }
    
  8. Functional interfaces and lambdas in Kotlin:

    • Kotlin interfaces can have a single abstract method, making them functional interfaces suitable for use with lambdas.
    interface MathOperation {
        fun operate(x: Int, y: Int): Int
    }
    
    val add: MathOperation = { x, y -> x + y }
    
  9. Interfaces and delegation in Kotlin:

    • Use delegation to implement interfaces by delegating to another object.
    interface Logger {
        fun log(message: String)
    }
    
    class ConsoleLogger : Logger {
        override fun log(message: String) {
            println("Log: $message")
        }
    }
    
    class App(private val logger: Logger) : Logger by logger
    
  10. Interfaces in Kotlin and Java interoperability:

    • Kotlin interfaces seamlessly interact with Java code.
    // Kotlin
    interface Printable {
        fun print()
    }
    
    // Java
    class JavaClass implements Printable {
        @Override
        public void print() {
            System.out.println("Printing...");
        }
    }