Use Kotlin Classes

May 22 2024 · Kotlin 1.9.24, Android 14, Kotlin Playground

Lesson 06: Implement Interfaces

Demo

Episode complete

Play next episode

Next
Transcript

Extending on interfaces, you’ll see that not every conventional rule must be followed. The Kotlin language allows you to build code that makes little logical sense but could help define behaviors.

You’re going to break the rules and show that the interface can hold the data, and you can manipulate it to achieve remarkable results.

First, define a Shape interface:

interface Shape {
  var name: String
    get() = names[this]?.uppercase() ?: "Unknown shape"
    set(value) {
      names[this] = value
    }

  var vertices: Int
    get() = vertexCount[this] ?: -1
    set(value) {
      vertexCount[this] = value
    }

  val details: String
    get() = "The $name has $vertices vertices"

  companion object {
    private val names = mutableMapOf<Shape, String>()
    private val vertexCount = mutableMapOf<Shape, Int>()
  }
}

Did you see what you just did? You introduced companion object and overridden name and vertices getters and setters to store instances of type Shape, specifically classes implementing Shape.

Now, add a few shapes:

class Triangle : Shape

class Square : Shape

Triangle and Square implement the Shape interface. Since Shape has default implementations for all its properties, these class definitions are sufficient.

Now, play with it in the main() function:

fun main() {
  val triangle = Triangle()
  triangle.name = "Triangle"
  triangle.vertices = 3

  val square = Square()
  square.name = "Square"
  square.vertices = 5

  println(triangle.details) // The TRIANGLE has 3 vertices
  println(square.details) // The SQUARE has 5 vertices
}

All seems to be in order here. But make the names map public:

  companion object {
    val names = mutableMapOf<Shape, String>()
  }

Now you can see that Shape has collected some information and is holding on to it. Add a few more lines to main():

  Shape.names.forEach { name ->
    println(name.value)
  }
  // Triangle
  // Square

You’ll observe that the Shape interface retains a record of all its implementing classes that have been used at least once.

Note: This example is only for showcasing the capabilities of the Kotlin language class constructs by using interfaces for holding the data. Try this at your own risk. Potential risks include poor memory management and garbage collection. For example, the Shape interface’s companion object holds references to all instances of Shape that have been used. This can lead to memory leaks if these instances are no longer needed but can’t be garbage collected because the Shape interface still holds a reference to them.

See forum comments
Cinema mode Download course materials from Github
Previous: Instruction Next: Conclusion