Created
October 9, 2019 08:12
-
-
Save erikhuizinga/31c37aa1e16c250309853d6175ec4a44 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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