2012-06-28 3 views
1

Каковы альтернативы SimpleDelegator, чтобы использовать полиморфизм без изменения базового объекта.Полиморфный Ruby SimpleDelegator

Это пример и проблема, которую SimpleDelegator не решит.

Цель состоит в том, чтобы иметь возможность обернуть исходный объект (delicious_food) с любым другим (yak_food), так что замещенный метод (delicious?) зависит от незамещенных методов лежащего в основе.

class Food 
    def initialize(color) 
    @color = color 
    end 

    def delicious? 
    color == :red 
    end 

    def color 
    @color 
    end 
end 

class FoodTasteOverride < SimpleDelegator 
    def color 
    :green 
    end 
end 

delicious_food = Food.new(:red) 
yak_food = FoodTasteOverride.new delicious_food 

delicious_food.delicious? # true - expected 
yak_food.delicious? # expecting false, but is true since the color come from delicious_food 

Что было бы альтернативой, которая фактически использовала бы замещенный метод? Недостатком является то, что вы не можете изменить базовый объект, его класс или клон.

Ограничение означает, что вы не можете сделать это:

yak_food = delicious_food.clone 
def yak_food.color 
    :green 
end 

ответ

3

Альтернативой является расширение метода вашего экземпляра с помощью расширения. (Это то, что делает большинство реализаций DCI для расширения объектов с поведением во время выполнения)

class Food 

    attr_reader :color 

    def initialize(color) 
    @color = color 
    end 

    def delicious? 
    self.color == :red 
    end 

end 

module FoodTasteOverride 
    def color 
    :green 
    end 
end 


normal_food = Food.new(:red) 
delicious_food = Food.new(:red) 
yak_food = normal_food.extend(FoodTasteOverride) 

puts delicious_food.delicious? # true - expected 
puts yak_food.delicious? #false because the color is now green. 
+0

Использование модулей в этом случае представляется мне более разумным. Декораторы не должны менять внутренности. –

+0

Отличная идея. По какой-то причине не думал о расширении. –

Смежные вопросы