Ruby中匿名结构的目的是什么?

时间:2011-12-22 11:21:44

标签: 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文档时,我认为“匿名”一词允许这样,但事实并非如此。

6 个答案:

答案 0 :(得分: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 :(得分:4)

好吧,如果你真的不想写一个带有访问器的类,你可以使用Structs。只写

很方便
Project = Struct.new(:name)

而不是

class Project
  attr_accesor :name
end

正如tokland正确地指出的那样(谢谢!),一个Struct也会自动为你提供一个很好的#initialize方法。因此,如果没有任何进一步的代码,可以进行以下操作:

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

答案 2 :(得分: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">

答案 3 :(得分: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>

答案 4 :(得分:1)

OpenStruct可能就是你想要的,但我最近遇到OpenStruct无法工作的情况,因为我在尝试访问未定义的属性时需要引发错误。 Struct 确实

os = OpenStruct.new
os.x = 1; os.y = 2;
os.z # returns nil

s = Struct.new(:x, :y).new
s.x = 1; s.y = 2;
s.z # raises NoMethodError

要记住一些事情。

答案 5 :(得分:0)

至于创建实例:

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