Skip to content

Instantly share code, notes, and snippets.

@erikhuizinga
Created October 9, 2019 08:12
Show Gist options
  • Save erikhuizinga/31c37aa1e16c250309853d6175ec4a44 to your computer and use it in GitHub Desktop.
Save erikhuizinga/31c37aa1e16c250309853d6175ec4a44 to your computer and use it in GitHub Desktop.
import kotlin.math.PI
fun main() {
val shapes = listOf(
Square(1.0),
Square(2.0),
Circle(3.0)
)
val shapeVisitors = listOf(
AreaShapeVisitor(),
PerimeterShapeVisitor(),
StringifierShapeVisitor(),
PrettyStringifierShapeVisitor()
)
// Here we do double dispatch:
// Depending on the type of the shape and the type of the visitor, we run some specific function
shapeVisitors.forEach { visitor ->
shapes.forEach { shape ->
println(shape.accept(visitor))
}
}
}
interface Shape {
fun <T> accept(shapeVisitor: ShapeVisitor<T>): T
}
class Square(val side: Double) : Shape {
override fun <T> accept(shapeVisitor: ShapeVisitor<T>) = shapeVisitor.visit(this)
}
class Circle(val radius: Double) : Shape {
override fun <T> accept(shapeVisitor: ShapeVisitor<T>) = shapeVisitor.visit(this)
}
interface ShapeVisitor<T> {
fun visit(square: Square): T
fun visit(circle: Circle): T
}
class AreaShapeVisitor : ShapeVisitor<Double> {
override fun visit(square: Square): Double {
val side = square.side
return side * side
}
override fun visit(circle: Circle): Double {
val radius = circle.radius
return PI * radius * radius
}
}
class PerimeterShapeVisitor : ShapeVisitor<Double> {
override fun visit(square: Square): Double {
val side = square.side
return 4 * side
}
override fun visit(circle: Circle) = 2 * PI * circle.radius
}
class StringifierShapeVisitor : ShapeVisitor<String?> {
override fun visit(square: Square) = square::class.simpleName
override fun visit(circle: Circle) = circle::class.simpleName
}
class PrettyStringifierShapeVisitor : ShapeVisitor<String> {
private val stringifier = StringifierShapeVisitor()
override fun visit(square: Square): String {
val string = stringifier.visit(square)
requireNotNull(string)
return "⃞⃞⃞$string⃞⃞⃞"
}
override fun visit(circle: Circle): String {
val string = stringifier.visit(circle)
requireNotNull(string)
return "•••$string•••"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment