2011-12-22 2 views
4

Они могут быть определены как этотКакова цель анонимной структуры в Ruby?

Struct.new(:x, :y)

Но что полезно может быть сделано с ними? В частности, как я могу создать экземпляр такой структуры? Это не работает

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

(вы получите TypeError: can't convert Hash into String).

Я использую Ruby 1.9.2.

UPDATE:

Хорошие указатели до сих пор, спасибо. Я полагаю, что причина, я спросил это было то, что я несколько раз обнаружили, что хотят сделать это

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

просто так, что я могу передать объект вокруг, где я могу написать obj.x вместо, скажем, инстанцировании хэш и необходимо написать obj[:x]. В этом случае я хочу, чтобы структура была действительно анонимно. Я не хочу загрязнять свое пространство имен чем-либо, называя то, что возвращается из вызова Struct.new. Ближе всего к тому, что, как уже было предложено в

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

Но как вы их любите яблоки? Я не уверен, что знаю. Можно ли ожидать, что сможет определить и создать экземпляр анонимной структуры за один раз (как часть основного Ruby)? Думаю, когда я прочитал официальные документы Ruby по адресу Struct.new, я предполагаю, что это слово «анонимный» позволяет это, но это не так.

+1

Это может быть также интересным для вас, чтобы пролистать: http://stackoverflow.com/questions/1177594/ruby-struct-vs-openstruct – gilligan

+0

Да, я обнаружил, что перед публикацией, но он не обращается к анонимным структурам напрямую. – Ben

ответ

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 для упоминания подкласса –

+1

+1 Первое объяснение, которое я прочитал, делает его действительно полезным. –

+0

Как и предложение OpenStruct, это больше всего похоже на то, что я ожидал, что смогу сделать с помощью 'Struct.new'. – Ben

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

+1

Кажется более уродливым, тогда красивым для меня. Я считаю, что это нарушение закона demeter. Я не очень хорошо знаком с использованием Struct. – Bohdan

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

Ну, вы можете использовать структуры, когда вы на самом деле не хотите, чтобы написать класс с аксессорами. Это удобно, чтобы просто написать

Project = Struct.new(:name) 

вместо

class Project 
    attr_accesor :name 
end 

Как tokland указал правильно (спасибо!), На структуру и дает хороший метод #initialize автомагически. Таким образом, возможно следующее без дальнейшего кода:

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

с помощью Struct вы также получаете инициализатор. (тип -> accesor -> accesor) – tokland

Смежные вопросы