2012-03-27 93 views
8

我有以下代碼:不理解類,模塊和類<<自我方法

class MyClass 
    module MyModule 
    class << self 

     attr_accessor :first_name 

     def myfunction 
     MyModule.first_name = "Nathan" 
     end 

    end 
    end 
end 

當我調用該方法myfunction像這樣,它工作正常:

> me = MyClass::MyModule.myfunction 
=> "Nathan" 
> me 
=> "Nathan" 

但如果我刪除class << self並將self.前綴添加到myfunction,則不起作用。

例如:

class MyClass 
    module MyModule 

    attr_accessor :first_name 

    def self.myfunction 
     MyModule.first_name = "Nathan" 
    end 

    end 
end 


> me = MyClass::MyModule.myfunction 
NoMethodError: undefined method `first_name=' for MyClass::MyModule:Module 

我想了解class << self方法。我認爲這是一種將self.前綴添加到其內部的所有方法的方法,但如果這是真的,那麼爲什麼它不起作用,如果我將其刪除並手動爲每個方法添加前綴self.

在此先感謝您的幫助。

+2

如果你真的想學習Ruby的元編程的細節,我建議[Ruby的元編程書由保羅·佩羅塔(http://pragprog.com/book/ppmetr/metaprogramming-ruby) 。 – sarnold 2012-03-28 00:04:41

回答

7

這是因爲您的attr_accessor :first_name也包含class << self

要做到這一點,你建議的方式,你可以使用mattr_accessor像這樣:

require 'active_support' 

class MyClass 
    module MyModule 

    mattr_accessor :first_name 

    def self.myfunction 
     MyModule.first_name = "Nathan" 
    end 

    end 
end 
+0

所以這是一個依賴於active_support的特定於rails的東西?我假設mattr_accessor是一個模塊特定的setter/getter方法? – Nathan 2012-03-28 03:22:39

+0

這是正確的。無論好壞,「mattr_accessor」只能通過Rails訪問。 – jnevelson 2012-03-28 06:44:09

+0

有一些有時我希望在常規Ruby中可用的東西,不僅僅是Rails或ActiveRecord。 – 2012-04-05 22:41:56

4

爲了更好地理解如何可以達到你想要什麼,看看下面的例子:

module PrintingModule 

    def self.included(object) 
    object.extend(ClassMethods) 
    end 

    module ClassMethods 

    def class_method_of_class 
     puts "I am class #{self.name}" 
    end 

    end 

    def instance_method_of_class 
    puts "My name is: #{@name}" 
    end 

    class << self 
    def static_module_method 
     puts "Printer version 1.0" 
    end 
    end 
end 

class SomeObject 
    include PrintingModule 
    def initialize(name) 
    @name = name 
    end 
end 

object = SomeObject.new("Something") 
object.instance_method_of_class 
SomeObject.class_method_of_class 
PrintingModule.static_module_method 

我希望這是更清楚了,請注意,這只是一種可能的方式(也有其他人)

UPDATE: 我會盡量更具體。當你在模塊上定義實例/單例方法時,你真正在做的是你定義了包含該模塊的類的實例方法,另一方面,在模塊上定義的類方法將成爲該模塊的類方法。第二個想到的是,attr_accessor爲給定參數的getter和setter創建實例方法。

現在要回答您的問題的一部分,在第一個示例中,您將在模塊的類上創建3個類方法。在第二個例子中,你正在創建1個類方法,你試圖訪問另一個類方法(setter),但你的getter和setter被定義爲實例方法=它們將成爲包含你的模塊的類方法的實例,你不能以這種方式得到他們=你無法獲得你的獲得者和制定者。 至於說明自我,以及我不熟練,但據我所知,當你使用「類< <自我」你打開對象的特徵類(每個對象有它自己的任何一個)(注意類,模塊或類的實例當然也是對象),您正在定義實例方法。對象的類方法Ruby =對象的本徵類的實例方法。所以,你可以舉例來說做到這一點:

text = "something" 
class << text 
    def say_hi 
    puts "Hi!" 
    end 
end 

text.say_hi 

當你(在這個例子字符串)創建類的實例,該實例得到它自己獨特的匿名類,它是類的子類。在該示例中,您已經在String類的匿名子類的特徵類上定義了實例方法。所以你可以在文本對象上使用方法「say_hi」,但不能在String類上使用。所以「類< <自我」正在打開這些特徵類。

另一方面,「自我」僅代表當前情境中的一個對象,這意味着在某些情況下(例如您的情況)相同。至於self.included方法,它只是一個回調方法,當模塊被包含在一個帶有代表對象的參數的類中時(這裏是類SomeObject),它會被調用。

我希望我已經回答了至少部分你的問題。 點擊此處瞭解詳情: Difference between 'self.method_name' and 'class << self' in Ruby

+0

我明白你是如何使用mixins的,除了'def self.included(object)...'之外,大多數情況下它都是有意義的。事情是,雖然我沒有那麼期望達到任何事情,但我試圖理解這種行爲。我不確定你的例子解釋了爲什麼'class << self'與混合模塊一起工作,但當嘗試訪問類方法時,'.self'前綴沒有。實際上,在我的示例中,我很困惑實例方法:first_name對於類調用是否可用。 – Nathan 2012-03-28 03:19:54

+0

我已經更新了我的答案,我希望它能回答您的問題中的至少一部分。祝你今天愉快。 – Giron 2012-03-28 21:44:55

相關問題