maneira preferida de implementar o padrão de visitante em linguagens dinâmicas?
-
09-06-2019 - |
Pergunta
Como exercício para mim mesmo, estava traduzindo um programa de exemplo para vários idiomas.Começando em C#, eu tinha uma interface de padrão de visitante assim:
interface Visitor
{
void Accept(Bedroom x);
void Accept(Bathroom x);
void Accept(Kitchen x);
void Accept(LivingRoom x);
}
Mudando para Ruby (ou python, ou qualquer outro), não recebo mais despacho do compilador com base no tipo.Devo fazer o envio no próprio visitante?
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
...
Ou devo fazer o envio nas diferentes especializações da sala:
class Bathroom<Room
def initialize(name)
super(name)
end
def accept(visitor)
visitor.acceptBathroom(self)
end
end
Ou existe outro idioma preferido usado em linguagens dinâmicas?
Solução
Minha recomendação é usar a abordagem anterior.Existem vantagens e desvantagens para cada abordagem.O primeiro é mais difícil de manter à medida que o número de tipos de quartos aumenta;o último é mais difícil à medida que o número de tipos de Cleaner aumenta.
Em Ruby, você poderia tentar
def accept(x)
send "accept#{x.class}".to_sym, x
end
PS:nem todas as linguagens digitadas dinamicamente são incapazes de despachar com base no tipo;alguns podem inferir o tipo ou, na falta disso, podem usar a conversão forçada para escolher o método adequado entre as opções sobrecarregadas.
Outras dicas
Eu iria com a segunda versão.O primeiro parece o tipo de cheiro de código que o Visitante deve resolver:instruções longas if-else-if ou switch-case.