2016-10-23 181 views
1

如何設置一些實例變量,如extend創建時一樣,initializeRuby:擴展實例變量

在這個例子中,變量設置擴展時,「迷失」:

module Mod 
    def self.extended(base) 
    @from_module = "Hello from Mod" 
    puts "Setting variable to: #{@from_module}" 
    end 

    def hello_from_module 
    return @from_module 
    end 
end 

class Klass 
    def initialize 
    @from_class = "Hello from Klass" 
    end 

    def hello_from_class 
    return @from_class 
    end 
end 

klass = Klass.new  #=> #<Klass:0x00000000ed8618 @from_class="Hello from Klass"> 
klass.extend(Mod)  #=> #<Klass:0x00000000ed8618 @from_class="Hello from Klass"> 
"Setting variable to: Hello from Mod" 

klass.hello_from_class #=> "Hello from Klass" 
klass.hello_from_module #=> nil (warning: instance variable @from_module not initialized) 
+1

該變量不會丟失。實例變量屬於對象(實例),這就是爲什麼它們被稱爲實例變量。您正在設置變量的實例是什麼?那麼這個方法是Mod的單例方法,所以'self'是'Mod',而實例變量是'Mod'的一個實例變量。 –

+0

值得注意的是,'return'在Ruby中是隱含的,在堆棧上留下的最後一件事是默認返回值,所以如果方法中的最後一件事是你想要的作爲返回值,它通常可以省略。 – tadman

回答

2

有許多方法可以做到你的描述。

最常見的一個辦法是使用instance_variable_getinstance_variable_set

module ModA 
    def self.extended(base) 
    base.instance_variable_set(:@from_module, "Hello from Mod A") 
    puts "Setting variable to: #{base.instance_variable_get(:@from_module)}" 
    end 

    def hello_from_module 
    return @from_module 
    end 
end 

另一種常見的方法是使用任何的evalexec方法。在這種情況下,instance_exec

module ModB 
    def self.extended(base) 
    base.instance_exec { @from_module = "Hello from Mod B" } 
    puts "Setting variable to: #{base.instance_exec { @from_module }}" 
    end 

    def hello_from_module 
    return @from_module 
    end 
end