2009-11-07 51 views
162

下面是一些代碼:實例變量:自VS @

class Person 
    def initialize(age) 
    @age = age 
    end 

    def age 
    @age 
    end 

    def age_difference_with(other_person) 
    (self.age - other_person.age).abs 
    end 

    protected :age 
end 

我想知道的是在age_difference_with方法使用@ageself.age之間的差異。

回答

237

寫入@age直接訪問實例變量@age。寫入self.age告訴對象自己發送消息age,它通常會返回實例變量@age - 但可以執行任意數量的其他操作,具體取決於在給定子類中如何實現age方法。例如,你可能有一個MiddleAgedSocialite類,它總是報告比其實際年齡小10歲的年齡。或者更實際上,PersistentPerson類可能懶惰地從持久性存儲中讀取數據,將其所有持久數據緩存在散列中。

+1

我曾經在rails中讀過一本書,不明白這個自我和@之間的區別,所以我應該總是在我的方法中使用self.var_name(這不是setter和getter)來使用公共接口創建我的數據,我花時間在getter和setter中定義它,對吧? – sarunw 2009-11-07 15:35:58

+0

... english ...你的意思是任何數量的東西。我沒有得到最後兩個例子。 – user2167582 2014-10-06 02:43:20

21

不同之處在於,它將該方法的使用與實施隔離開來。如果財產的實施發生變化 - 比如說保留出生日期,然後根據現在和出生日期之間的時間差計算年齡 - 那麼取決於方法的代碼不需要改變。如果它直接使用該屬性,則該更改將需要傳播到代碼的其他區域。從這個意義上講,直接使用屬性比使用類提供的接口更脆弱。

+12

哦,因爲self.age可以引用實例變量或實例方法嗎? – 2013-03-11 23:39:13

2

沒有任何區別。我懷疑這只是爲了看到self.ageother_person.age彼此靠近的文件值。

我想這種使用確實允許將來寫入一個實際的getter,這可能會做一些比只返回一個實例變量更復雜的東西,在這種情況下,該方法不需要改變。

但是,這是一個不太可能的抽象擔心,畢竟,如果對象的實現改變了它是合理的改變其他方法,在某些時候對象本身的簡單引用是完全合理的。

在任何情況下,age屬性的抽象仍然沒有解釋明確使用的self,因爲只是簡單的age也援引了訪問。

5

是當你繼承Struct.new一類是產生一個初始化器(How to generate initializer in Ruby?

一個整潔的方式警告
class Node < Struct.new(:value) 
    def initialize(value) 
     @value = value 
    end 
    def show() 
     p @value 
     p self.value # or `p value` 
    end 
end 

n = Node.new(30) 
n.show() 

將返回

30 
nil 

然而,當您刪除初始化,它將返回

nil 
30 

隨着類定義

class Node2 
    attr_accessor :value 
    def initialize(value) 
     @value = value 
    end 
    def show() 
     p @value 
     p self.value 
    end 
end 

您應該提供構造函數。

n2 = Node2.new(30) 
n2.show() 

將返回

30 
30 
-3

@age - 絕對是實例變量年齡

self.age - 指的是實例屬性的年齡。

-1

第一個答案是完全正確的,但作爲一個相對的新手,它並沒有立即清楚它的含義(發送消息給自己,呃呃......)。我認爲一個簡短的例子將有所幫助:

class CrazyAccessors 
    def bar=(val) 
    @bar = val - 20 # sets @bar to (input - 20) 
    end 
    def bar 
    @bar 
    end 

    def baz=(value) 
    self.bar = value # goes through `bar=` method, so @bar = (50 - 20) 
    end 

    def quux=(value) 
    @bar = value  # sets @bar directly to 50 
    end 
end 

obj = CrazyAccessors.new 
obj.baz = 50 
obj.bar # => 30 
obj.quux = 50 
obj.bar # => 50 
+2

這個例子使事情更加混亂。 – 2016-07-30 22:25:35

+0

我很抱歉,但這個例子對我來說沒有足夠的評論。我無法追隨你的推理。 – kouty 2016-12-11 19:04:33