一般来说,与Struct相比,使用OpenStruct的优点和缺点是什么?什么样类型的通用用例适合每一个?


当前回答

使用@Robert代码,我将Hashie::Mash添加到基准测试项中,得到了这样的结果:

                           user     system      total        real
Hashie::Mash slow      3.600000   0.000000   3.600000 (  3.755142)
Hashie::Mash fast      3.000000   0.000000   3.000000 (  3.318067)
OpenStruct slow       11.200000   0.010000  11.210000 ( 12.095004)
OpenStruct fast       10.900000   0.000000  10.900000 ( 12.669553)
Struct slow            0.370000   0.000000   0.370000 (  0.470550)
Struct fast            0.140000   0.000000   0.140000 (  0.145161)

其他回答

使用@Robert代码,我将Hashie::Mash添加到基准测试项中,得到了这样的结果:

                           user     system      total        real
Hashie::Mash slow      3.600000   0.000000   3.600000 (  3.755142)
Hashie::Mash fast      3.000000   0.000000   3.000000 (  3.318067)
OpenStruct slow       11.200000   0.010000  11.210000 ( 12.095004)
OpenStruct fast       10.900000   0.000000  10.900000 ( 12.669553)
Struct slow            0.370000   0.000000   0.370000 (  0.470550)
Struct fast            0.140000   0.000000   0.140000 (  0.145161)

与Structs相比,OpenStructs使用的内存明显更多,运行速度更慢。

require 'ostruct' 

collection = (1..100000).collect do |index|
   OpenStruct.new(:name => "User", :age => 21)
end

在我的系统上,以下代码在14秒内执行,消耗了1.5 GB内存。你的里程可能有所不同:

User = Struct.new(:name, :age)

collection = (1..100000).collect do |index|
   User.new("User",21)
end

这几乎是在瞬间完成的,消耗了26.6 MB的内存。

两者的用例完全不同。

你可以把Ruby 1.9中的Struct类看作相当于c中的Struct声明。new接受一组字段名作为参数,并返回一个新Class。类似地,在C语言中,struct声明接受一组字段,并允许程序员像使用任何内置类型一样使用新的复杂类型。

Ruby:

Newtype = Struct.new(:data1, :data2)
n = Newtype.new

C:

typedef struct {
  int data1;
  char data2;
} newtype;

newtype n;

OpenStruct类可以与c语言中的匿名结构声明相比较。它允许程序员创建复杂类型的实例。

Ruby:

o = OpenStruct.new(data1: 0, data2: 0) 
o.data1 = 1
o.data2 = 2

C:

struct {
  int data1;
  char data2;
} o;

o.data1 = 1;
o.data2 = 2;

下面是一些常见的用例。

OpenStructs可以很容易地将散列转换为一次性对象,从而响应所有散列键。

h = { a: 1, b: 2 }
o = OpenStruct.new(h)
o.a = 1
o.b = 2

struct可以用于简化类定义。

class MyClass < Struct.new(:a,:b,:c)
end

m = MyClass.new
m.a = 1

使用OpenStruct,您可以任意创建属性。另一方面,Struct必须在创建时定义其属性。选择一种还是另一种应该主要基于您以后是否需要能够添加属性。

The way to think about them is as the middle ground of the spectrum between Hashes on one side and classes on the other. They imply a more concrete relationship amongst the data than does a Hash, but they don't have the instance methods as would a class. A bunch of options for a function, for example, make sense in a hash; they're only loosely related. A name, email, and phone number needed by a function could be packaged together in a Struct or OpenStruct. If that name, email, and phone number needed methods to provide the name in both "First Last" and "Last, First" formats, then you should create a class to handle it.

看一下与新方法相关的API。这里有很多不同之处。

就我个人而言,我非常喜欢OpenStruct,因为我不需要预先定义对象的结构,只需要添加我想要的东西。我猜这将是它的主要(缺点)优势?

http://www.ruby-doc.org/core/classes/Struct.html http://www.ruby-doc.org/stdlib/libdoc/ostruct/rdoc/classes/OpenStruct.html