Lesson 13 / 25

Interfaces, Inheritance and Visibility

open, abstract, override and visibility modifiers.

Explicit extension points

Classes and members are final by default; mark them open to allow subclassing or overriding, and use override explicitly in subclasses. An abstract class cannot be instantiated and may declare abstract members. Interfaces can declare abstract members, properties without state, and methods with default implementations; a class can implement many interfaces but extend one class. Visibility modifiers are public (the default), private (inside the class or file), protected (class and subclasses) and internal (visible within the same module, such as a Gradle source set).

Inheritance by choice, composition by default

Kotlin classes are final unless opened, and objects, companions and delegation replace many classic patterns.

Three ideas: interfaces and modifiers, objects and companions, delegation.
Figure 5.1 — Interface, implementation and delegate.

An interface with a default method

Explicit open and override.

interface Shape {
    val name: String
    fun area(): Double
    fun describe(): String = "$name with area ${"%.2f".format(area())}"   // default
}

abstract class Polygon(override val name: String) : Shape {
    abstract val sides: Int
}

open class Rectangle(val w: Double, val h: Double) : Polygon("rectangle") {
    override val sides = 4
    override fun area() = w * h
}

class Square(side: Double) : Rectangle(side, side) {
    override fun describe() = "square: " + super.describe()
}

internal fun debugShapes(): List<Shape> = listOf(Rectangle(2.0, 3.0), Square(2.0))

Final by default is a feature

Closed classes make it safe to change implementation details. Open a class only when you deliberately design it for extension; otherwise prefer composition and interfaces.

Quick check: What does the `internal` modifier mean?

  • Visible only inside the class
  • Visible everywhere within the same module
  • Visible only to subclasses
  • Visible only within the same file
Answer

Visible everywhere within the same module — internal is module-wide visibility.