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:
作为我自己的练习,我正在将一个示例程序翻译成各种语言。从C#开始,我有一个访问者模式界面,如下所示:
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?
转移到ruby(或python,或其他),我不再根据类型从编译器调度。我应该在访客本身进行调度吗?
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?
或者是否有另一种在动态语言中使用的首选习语?
2 个解决方案
#1
3
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
在Ruby中,你可以试试
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.
PS:并非所有动态类型的语言都无法根据类型进行调度;有些人可以推断类型,或者失败,可以使用强制转换在重载选项中选择正确的方法。
#2
3
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.
我会选择第二个版本。第一个看起来像访问者应该解决的那种代码气味:long if-else-if或switch-case语句。
#1
3
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
在Ruby中,你可以试试
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.
PS:并非所有动态类型的语言都无法根据类型进行调度;有些人可以推断类型,或者失败,可以使用强制转换在重载选项中选择正确的方法。
#2
3
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.
我会选择第二个版本。第一个看起来像访问者应该解决的那种代码气味:long if-else-if或switch-case语句。