2010-02-19 103 views
13

如何在mixin方法中訪問實例變量?我可以想到2種方法,但都顯得有問題。如何訪問mixin方法中的實例變量?

  1. 讓mixin方法直接訪問實例變量,就像任何類方法一樣,比如self.text。問題在於它對mixin方法的使用位置施加了限制,並強制類進行混合,以特定方式命名特定的實例方法。

  2. 傳遞實例變量作爲參數的混入的方法,這將導致這樣的代碼:

例如

self.do_something(self.text) 

@thing.do_something(@thing.text) 

看起來對我來說令人討厭,並且不符合面向對象的原則。

有沒有其他辦法可以做到這一點?我有權擔心嗎?

回答

21

一般,避免混入訪問成員變量:這是一種非常緊密的耦合形式,可能會使未來的重構變得不必要的困難。

一個有用的策略是讓Mixin始終通過訪問器訪問變量。所以,相反的:

#!/usr/bin/ruby1.8 

module Mixin 

    def do_something 
    p @text 
    end 

end 

class Foo 

    include Mixin 

    def initialize 
    @text = 'foo' 
    end 

end 

Foo.new.do_something  # => "foo" 

的混入訪問「文本」訪問,這是由包括類定義:

module Mixin 

    def do_something 
    p text 
    end 

end 

class Foo 

    attr_accessor :text 

    include Mixin 

    def initialize 
    @text = 'foo' 
    end 

end 

Foo.new.do_something  # => "foo" 

如果你需要包括的Mixin這個班上嗎?

class Foo 

def initialize 
    @text = "Text that has nothing to do with the mixin" 
end 

end 

使用混入普通和常見的數據名稱時,包括類使用相同的名稱可能會導致衝突。在這種情況下,有混入查找數據與不太常見的名字:

module Mixin 

    def do_something 
    p mixin_text 
    end 

end 

,並讓包括類定義相應的訪問:

class Foo 

    include Mixin 

    def initialize 
    @text = 'text that has nothing to do with the mixin' 
    @something = 'text for the mixin' 
    end 

    def mixin_text 
    @something 
    end 

end 

Foo.new.do_something  # => "text for the mixin" 

通過這種方式,存取作爲排序混音輸入數據和包含類別數據之間的「阻抗匹配器」或「翻譯器」。

+0

謝謝韋恩,你真的清除了這一點。 – dangerousdave 2010-02-19 20:54:03

1

您可以在此模塊中提供這種情況下你自己的方法,但你必須要小心,不要覆蓋現有的方法

例(模塊你是混合):

def text 
    @text ||= "" 
end 
+1

感謝Kylo,但這似乎仍然限制了mixin的使用方式。拉入它的類必須仍然有一個實例變量@text。 – dangerousdave 2010-02-19 12:25:44

2

實例變量名用@例如ruby開始。 @variable。您可以從一個模塊使用這個名稱存取權限他們你有

module M 
    def t 
    @t 
    end 
end 

class A 
    include M 
    def initialize(t) 
    @t= t 
    end 
end 

A.new(23).t # => 23 

如果您wan't訪問@t當它不是在你的類中定義之前,你可以這樣來做

module M 
    def t 
    instance_variable_defined?("@t") ? @t : nil 
    end 
end