Kotlin visitor pattern

How to write a visitor pattern in Kotlin

An example of a visitor pattern in Kotlin.

Table of contents for design patterns in Kotlin

In object-oriented programming and software engineering, the visitor design pattern is a way of separating an algorithm from an object structure on which it operates. A practical result of this separation is the ability to add new operations to existing object structures without modifying the structures. It is one way to follow the open/closed principle. Wikipedia

Example:

ShapeVisitable

interface ShapeVisitable {
    fun <R> accept(visitor: ShapeVisitor<R>): R
}

ShapeVisitor

interface ShapeVisitor<out R> {

    fun visit(shape: Circle): R

    fun visit(shape: Square): R
}

Circle

class Circle(val diameter: Long) : ShapeVisitable {
    override fun <R> accept(visitor: ShapeVisitor<R>): R = visitor.visit(this)
}

Square

class Square(val size: Long) : ShapeVisitable {
    override fun <R> accept(visitor: ShapeVisitor<R>): R = visitor.visit(this)
}

PrintVisitor

class PrintVisitor : ShapeVisitor<String> {

    override fun visit(shape: Circle): String = "Circle: diameter=${shape.diameter}"

    override fun visit(shape: Square): String = "Square: size=${shape.size}"
}

FileSaveVisitor

class FileSaveVisitor : ShapeVisitor<String> {

    override fun visit(shape: Circle): String = "C:d=${shape.diameter}"

    override fun visit(shape: Square): String = "S:s=${shape.size}"
}

Usage:

fun main() {
    val shapes = mutableListOf<ShapeVisitable>().apply {
        add(Circle(10))
        add(Square(12))
    }

    val printVisitor = PrintVisitor()
    val fileSaveVisitor = FileSaveVisitor()

    shapes.map { shape -> shape.accept(printVisitor) }.forEach {
        println(it)
    }

    File("visitor_shapes.txt").writer().use { writer ->
        writer.write("")
        shapes.map { shape -> shape.accept(fileSaveVisitor) }.forEach { shapeData ->
            writer.appendln(shapeData)
        }
        writer.flush()
    }
}

Result

Circle: diameter=10
Square: size=12

visitor_shapes.txt

C:d=10
S:s=12