Question

As an exercise for myself, I was translating a sample program into various languages. Starting in C#, I had a visitor-pattern interface like so:

interface Visitor
    {
        void Accept(Bedroom x);
        void Accept(Bathroom x);
        void Accept(Kitchen x);
        void Accept(LivingRoom x);
    }

Moving to ruby (or python, or whatever), I no longer get dispatch from the compiler based on type. Should I do the dispatch in the visitor itself?

class Cleaner

  def accept(x)
    acceptBedroom(x) if Bedroom === x
    acceptBathroom(x) if Bathroom === x
    acceptKitchen(x) if Kitchen===x
    acceptLivingRoom(x) if LivingRoom===x
  end

  ...

Or should I do the dispatch in the different specializaions of the room:

class Bathroom<Room
  def initialize(name)
    super(name)
  end
  def accept(visitor)
    visitor.acceptBathroom(self)
  end
end

Or is there another preferred idiom that is used in dynamic languages?

Was it helpful?

Solution

My recommendation is to use the former approach. There are pluses and minuses for each approach. The former is harder to maintain as the number of Room types grows; the latter is harder as the number of Cleaner types grows.

In Ruby, you could try

def accept(x)
  send "accept#{x.class}".to_sym, x
end

PS: not all dynamically typed languages are unable to do dispatch based on type; some can infer type, or failing that, can used forced casting to pick the proper method among the overloaded options.

OTHER TIPS

I would go with the second version. The first one looks like the kind of code smell that Visitor is supposed to solve: long if-else-if or switch-case statements.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top