They can be defined like this
Struct.new(:x, :y)
But what can usefully be done with them? Specifically, how can I create an instance of such a struct? This doesn't work
Struct.new(:x => 1, :y => 1)
(you get TypeError: can't convert Hash into String
).
I'm using Ruby 1.9.2.
UPDATE:
Good pointers so far, thanks. I suppose the reason I asked this was that I have several times found myself wanting to do this
Struct.new(:x => 1, :y => 1)
just so that I can pass an object around where I can write obj.x
instead of, say, instantiating a hash and having to write obj[:x]
. In this case I want the structure to be really anonymous - I don't want to pollute my namespace with anything by naming what is returned from the Struct.new
call. The closest thing to that, as already suggested is
Struct.new(:x, :y).new(1, 1)
But how do you like them apples? I'm not sure I do. Is it reasonable to expect to be able to define and instantiate an anonymous struct in one go (as part of core Ruby)? I guess when I read the official Ruby docs on Struct.new
I assume the word 'anonymous' allows this, but it doesn't.
A Struct is a convenient way to bundle a number of attributes together, using accessor methods, without having to write an explicit class. The Struct class generates new subclasses that hold a set of members and their values. For each member a reader and writer method is created similar to Module#attr_accessor .
An OpenStruct is a data structure, similar to a Hash , that allows the definition of arbitrary attributes with their accompanying values. This is accomplished by using Ruby's metaprogramming to define methods on the class itself.
Struct.new
returns a Class
, so you can, for example, assign it to a constant like this:
Point = Struct.new(:x, :y)
or subclass it:
class Point < Struct.new(:x, :y)
# custom methods here
# ...
end
In both cases, you can use the resulting class like this:
Point.new(3, 5)
If you don't want to create a specific class (because you need to instantiate an object of that class only once), consider to use OpenStruct
instead:
require 'ostruct'
point = OpenStruct.new(:x => 3, :y => 5)
You first create a struct, and then you can create instances of it. It's a way of creating data objects without having to declare a class. Basically it's the same as a hash, but it's more clean to access the objects. You can get stuff out of it by referencing it via ordinary accessor methods.
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">
Well, you can use Structs when you don't actually want to write a class with accessors. It's handy to just write
Project = Struct.new(:name)
instead of
class Project
attr_accesor :name
end
As tokland pointed out correctly (thanks!), a Struct also gives you a nice #initialize method automagically. So the following is possible without any further code:
Project = Struct.new(:name)
p = Project.new('Quadriloptic Curves')
I'm hot sure about purpose but Struct.new
returns class so
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With