2011-12-22 38 views
4

他們可以這樣Ruby中匿名結構的目的是什麼?

Struct.new(:x, :y)

中定義,但有什麼可以有效地和他們做了什麼?具體來說,我如何創建這樣一個結構的實例?這不起作用

Struct.new(:x => 1, :y => 1)

(你TypeError: can't convert Hash into String)。

我正在使用Ruby 1.9.2。

更新:

好指針,迄今爲止,謝謝。我想我問這個的原因是我有好幾次發現自己想要做這個

Struct.new(:x => 1, :y => 1)

只是,這樣我可以繞過我在哪裏可以寫obj.x代替,比如說一個對象,實例化一個散列並且必須寫obj[:x]。在這種情況下,我想要的結構是真的是匿名 - 我不想通過命名從Struct.new調用返回的內容來污染我的命名空間。最接近的東西,如已經建議是

Struct.new(:x, :y).new(1, 1)

但是你怎麼喜歡他們的蘋果?我不確定我是否確定。期望能夠一次性定義和實例化一個匿名結構(作爲核心Ruby的一部分)是否合理?我猜當我閱讀Struct.new上的官方Ruby文檔時,我認爲「匿名」這個詞允許這樣做,但事實並非如此。

+1

這可能是也很有趣,爲您滑過:http://stackoverflow.com/questions/1177594/ruby-struct-vs-openstruct – gilligan 2011-12-22 11:30:22

+0

是的,我發現之前發佈但它不直接解決匿名結構。 – Ben 2011-12-22 12:43:21

回答

18

Struct.new返回Class,這樣你就可以,例如,將其分配給這樣一個常數:

Point = Struct.new(:x, :y) 

或子類:

class Point < Struct.new(:x, :y) 
    # custom methods here 
    # ... 
end 

在這兩種情況下,您可以使用生成的類是這樣的:

Point.new(3, 5) 

如果你不希望創建一個特定的類(因爲你需要實例化類只有一次的對象),考慮使用OpenStruct代替:

require 'ostruct' 

point = OpenStruct.new(:x => 3, :y => 5) 
+1

+1提到子類 – 2011-12-22 11:42:53

+1

+1首先解釋我讀過,這實際上聽起來有點用處。 – 2011-12-22 12:25:17

+0

就像'OpenStruct'建議一樣 - 這很像我期望能用'Struct.new'做的事情。 – Ben 2011-12-22 12:57:37

2

我好熱肯定目的,但Struct.new收益類,所以

irb(main):001:0> Struct.new(:x,:y) 
=> #<Class:0x2914110> 
irb(main):002:0> Struct.new(:x,:y).new(1,2) 
=> #<struct x=1, y=2> 
+2

是的,那第二行不是很美就是很醜,我不能決定! – Ben 2011-12-22 12:46:18

+1

似乎更醜陋,然後對我很美麗。這是違反德米特法則的,我認爲。我不熟悉s Struct的用法。 – Bohdan 2011-12-22 15:16:05

3

您首先創建一個結構體,然後您可以創建它的實例。這是創建數據對象而不必聲明類的一種方法。基本上它與散列相同,但訪問對象更加乾淨。你可以通過普通的訪問器方法來引用它。

http://www.ruby-doc.org/core-1.9.3/Struct.html

# Create a structure with a name in Struct 
Struct.new("Customer", :name, :address) #=> Struct::Customer 
Struct::Customer.new("Dave", "123 Main") #=> #<struct Struct::Customer name="Dave", address="123 Main"> 

# Create a structure named by its constant 
Customer = Struct.new(:name, :address)  #=> Customer 
Customer.new("Dave", "123 Main")   #=> #<struct Customer name="Dave", address="123 Main"> 
0

至於創建實例:

User = Struct.new(:user,:password) 
u = User.new("john","secret") 
4

好了,你可以使用的Structs時,你實際上並沒有想寫與存取類。它的方便,只是寫的

Project = Struct.new(:name) 

代替

class Project 
    attr_accesor :name 
end 

由於tokland指出正確(感謝!),一個結構也給你一個很好的方法#initialize自動的。所以下面是可能沒有任何進一步的代碼:

Project = Struct.new(:name) 
p = Project.new('Quadriloptic Curves') 
+1

與結構你也得到一個初始化。 (type - > accesor - > accesor) – tokland 2011-12-22 11:36:33