2012-03-16 190 views
6

有什麼區別:區別 「A級; B類」 和 「類A :: B」

class A 
    class B 
    end 
end 

class A 
end 

class A::B 
end 

更新:這兩個方法都沒有一模一樣。

在第二種方法中,B無法訪問A中定義的常量。

另外,作爲馬修斯莫雷拉正確地指出,在第二方法中,A必須A::B之前定義可以被定義。

還有什麼其他的不同嗎?

回答

8

在Ruby中,模塊和類分別是ModuleClass類的實例,。他們從他們被分配到的常數中得到他們的名字。當你寫:

class A::B 
    # ... 
end 

您有效地寫着:

A::B ||= Class.new do 
    # ... 
end 

有效期不變賦值語法和假定A恆已經正確初始化,它指的是ModuleClass

例如,考慮類是如何通常定義:

class A 
    # ... 
end 

什麼是有效的情況是這樣的:

Object::A ||= Class.new do 
    # ... 
end 

現在,當你寫:

class A 
    class B 
    # ... 
    end 
end 

究竟是什麼碰巧看起來像這樣:

(Object::A ||= Class.new).class_eval do 
    (A::B ||= Class.new).class_eval do 
    # ... 
    end 
end 

這裏發生了什麼,以便:

  1. Class實例asssigned到ObjectA不變,除非它已經被初始化。
  2. 一個新的Class實例被分配到B常量A,除非它已經被初始化。

這確保試圖定義任何內部類之前所有外類存在。

範圍也有變化,可以直接訪問A的常量。比較:

class A 
    MESSAGE = "I'm here!" 
end 

# Scope of Object 
class A::B 
    # Scope of B 
    puts MESSAGE # NameError: uninitialized constant A::B::MESSAGE 
end 

# Scope of Object 
class A 
    # Scope of A 
    class B 
    # Scope of B 
    puts MESSAGE # I'm here! 
    end 
end 

this blog post,Ruby的核心團隊稱之爲 「當前類的」 cref。不幸的是,作者沒有詳細說明,但正如他指出的,它與self的背景是分開的。


As explained here,該cref鏈表表示模塊在某個時間點上築巢。

當前cref用於恆定和類變量查找和 爲defundefalias


正如其他人所說,他們表達了同樣的事情不同的方式。

但是,有一個微妙的區別。當您編寫class A::B時,您的假定A類已被定義。如果沒有,你將得到一個NameErrorB根本不會被定義。

編寫正確的嵌套模塊:

class A 
    class B 
    end 
end 

確保A類存在試圖定義B之前。

+1

我已更新問題以顯示這兩種方法不相同。 – nickh 2012-03-16 17:14:43

+0

@nickh,你不需要編輯問題來包含答案。你應該[upvote有用的答案,並接受肯定回答你的問題](http://stackoverflow.com/faq#howtoask)。 – 2012-03-16 17:47:21

+0

事情是,他們都沒有回答這個問題。所有的答案都說2種方法是相同的,但他們並不相同。 – nickh 2012-03-16 18:36:50

1

它們是相同的。他們是寫同一事物的不同方式。第一個是編寫它的天真方式,但是一旦類/模塊變大,很難跟蹤嵌套。使用第二種方法,可以避免嵌套在外觀中。

+1

我已更新問題以顯示這兩種方法不相同。 – nickh 2012-03-16 17:15:05

+0

@nickh我認爲這些差異是微不足道的,並且是先決條件的,所以我沒有提及它們。指出它們與說「嗯,字符串'類B'看起來不同於'類A :: B'」沒有什麼不同,但你沒有提到這一點。 – sawa 2012-03-20 17:22:46

3

兩種不同的方式來說相同的事情。那就是B類是內部類或嵌套類,只能通過A接口訪問。

> class A 
.. def say 
.... "In A" 
....end 
.. 
.. class B 
.... def say 
...... "In B" 
......end 
....end 
..end 
=> nil 

> A.new.say 
=> "In A" 
> B.new.say 
=> #<NameError: uninitialized constant B> 
> A::B.new.s­ay 
=> "In B" 

> class A 
.. def say 
.... "In A" 
....end 
..end 
=> nil 

> class A::B 
.. def say 
.... "In B" 
....end 
..end 
=> nil 

> A.new.say 
=> "In A" 
> B.new.say 
=> #<NameError: uninitialized constant B> 
> A::B.new.s­ay 
=> "In B" 
> 
+1

我已更新問題以顯示這兩種方法不一樣。 – nickh 2012-03-16 17:14:37

相關問題