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.
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.