Skip to content

Instantly share code, notes, and snippets.

@Ioane5
Created November 30, 2019 22:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ioane5/d60f488b543b8e0f26044c06de28705a to your computer and use it in GitHub Desktop.
Save Ioane5/d60f488b543b8e0f26044c06de28705a to your computer and use it in GitHub Desktop.
How not to use Visitor Pattern
package models
sealed class Expression
class Literal(val value: Double) : Expression()
class Addition(val left: Expression, val right: Expression) : Expression()
abstract class ExpressionOperator<T> {
abstract fun operate(literal: Literal): T
abstract fun operate(addition: Addition): T
fun operate(expression: Expression): T = when (expression) {
is Literal -> operate(expression)
is Addition -> operate(expression)
}
}
class ExpressionStringifier : ExpressionOperator<String>() {
override fun operate(literal: Literal) = literal.value.toString()
override fun operate(addition: Addition): String {
return "(${operate(addition.left)} + ${operate(addition.right)})"
}
}
class ExpressionCalculator : ExpressionOperator<Double>() {
override fun operate(literal: Literal) = literal.value
override fun operate(addition: Addition) = operate(addition.left) + operate(addition.right)
}
fun main() {
val expression = Addition(Literal(1.0), Literal(1000.0)) as Expression
// Expression to string
val expressionStr = ExpressionStringifier().operate(expression)
println("Expression: $expressionStr")
// Calculate Expression
val value = ExpressionCalculator().operate(expression)
println("Value: $value")
}
@Ioane5
Copy link
Author

Ioane5 commented Nov 30, 2019

I dislike visitor pattern, because it's confusing.
I think they way object accepts something that is not part of it, just to calculate upon, is not natural.
Using dynamic way seems prettier, but it brings danger or runtime type exceptions.

So, I think this can be completely avoided by using sealed types and when expression, that is exhaustive, meaning that, it will remind you to handle all the types, because, it's sealed and therefore, all the inherited models are known.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment