2013-07-08 69 views
2

我在嘗試一些關於如何在內部聲明類以及聲明類時會發生什麼的代碼。我得知,當一個類被聲明時,一個'Class'對象被創建並且一個常量與被聲明的類的名字被創建。例如ruby​​對象模型和類聲明

MyClass = Class.new 
MyClass.class => Class 
MyClass.superclass => Object 
Class.constants.include? :MyClass => true 

我也嘗試

x = Class.new => #<Class:0xd886938> 
x.class => Class 
x.superclass => Object 
Class.constants.include? :x => false #why so??? 

這意味着 'X' 是一個類。 I M困惑的原因

class x 
    def say_hi 
    'hi' 
    end 
end 

SyntaxError: (irb):121: class/module name must be CONSTANT 

爲什麼會出現這種情況?

--- UPDATE ---

我試圖

def x.x_method 
    'x class method' 
end 

,做

x.methods.include? :x_method => true 

同樣

x.singleton_methods.include? :x_method => true 

主要

x.methods - MyClass.methods => [:x_method] 

上面一行指出x是一個類,因爲它是類Class的一個對象。由於所有用戶定義的類是Class類的對象,則它們的初始方法也應該是相同的,除非一些單方法被聲明爲一個特定的類(在上述情況下x具有單方法)

x => #<Class:0xd886938> 
obj_x = x.new => #<#<Class:0xd886938>:0xd30caac> 
obj_x.class => #<Class:0xd886938> 

上面代碼進一步加強了x是一個類,因爲它允許我創建新的對象。如果x本來是一個實例,那麼new將失敗並出現錯誤。

我的問題是,爲什麼紅寶石允許我以特定的方式聲明一個類?如果它不是一個類,那它爲什麼表現得像一個?

+0

@mbratch但一切都是紅寶石是一個對象。即Class類的一個實例。比如說,String類是Class類的一個實例。 –

+1

x是對一個類的引用。你不能從它的名字訪問這個類,因爲它沒有它,因爲ruby期望所有的類名都是常量,而你沒有提供它。因此'SyntaxError:(irb):121:class/module name必須是CONSTANT'錯誤。你可以訪問你創建的這個類的唯一方法就是你存儲在x中的這個引用。 – Cezar

+0

嘗試下面的命令,看看它們與'x'有什麼不同。而不是以#的形式查看對任意未命名類的引用,這是'x'引用的內容,您將看到類名。 'obj_MyClass = MyClass.new'和'obj_MyClass.class' – Cezar

回答

4

Ruby解釋器只能看到以大寫字母開頭的東西作爲常量。這就是爲什麼不包括你的「類」 xClass.constants

This

Naming conventions

Ruby enforces some naming conventions. If an identifier starts with a capital letter, it is a constant. If it starts with a dollar sign ($), it is a global variable. If it starts with @, it is an instance variable. If it starts with @@, it is a class variable.

由於類名應該是常數,x在你的代碼是不是類的名稱。它是一個持有類的變量,恰好沒有正確的分配名稱。 (你可以通過輸入x.name,看到它返回nil驗證,作爲對他的回答提出由@ZachKemp

總之,你不能給一個類,與Ruby的小寫字母開頭的名稱。

2

正如您發現的那樣,您可以將類視爲Ruby中的第一類對象。在您創建一個新類爲x = Class.new的情況下,您已將類實例對象分配給一個變量,這與給它一個名稱不同(您可以發送查詢方法x.name以驗證名稱是nil)。然後,您可以將該變量分配給一個常量(MyClass = x)以給它一個永久名稱。

class聲明是一個關鍵字,需要一個常量開始。兩種創建類的方法創建相同的事物(Class的一個實例),並且您可以使用任意一種方法(儘管第一種方法通常只在特殊情況下使用)。

+1

有趣...'MyClass = x'改變'x'的行爲.. – jozefg

+0

哪種行爲? –

+0

'x.name'從'nil'變成'MyClass'。這是有道理的,但認爲賦值應該影響賦值的語義很奇怪 – jozefg