一般来说,与Struct相比,使用OpenStruct的优点和缺点是什么?什么样类型的通用用例适合每一个?
当前回答
使用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.
其他回答
Not actually an answer to the question, but a very important consideration if you care about performance. Please notice that every time you create an OpenStruct the operation clears the method cache, which means your application will perform slower. The slowness or not of OpenStruct is not just about how it works by itself, but the implications that using them bring to the whole application: https://github.com/charliesome/charlie.bz/blob/master/posts/things-that-clear-rubys-method-cache.md#openstructs
其他指标:
require 'benchmark'
require 'ostruct'
REP = 100000
User = Struct.new(:name, :age)
USER = "User".freeze
AGE = 21
HASH = {:name => USER, :age => AGE}.freeze
Benchmark.bm 20 do |x|
x.report 'OpenStruct slow' do
REP.times do |index|
OpenStruct.new(:name => "User", :age => 21)
end
end
x.report 'OpenStruct fast' do
REP.times do |index|
OpenStruct.new(HASH)
end
end
x.report 'Struct slow' do
REP.times do |index|
User.new("User", 21)
end
end
x.report 'Struct fast' do
REP.times do |index|
User.new(USER, AGE)
end
end
end
对于那些没有耐心的人来说,他们想要了解基准测试结果,而不需要自己运行它们,下面是上面代码的输出(在MB Pro 2.4GHz i7上)
user system total real
OpenStruct slow 4.430000 0.250000 4.680000 ( 4.683851)
OpenStruct fast 4.380000 0.270000 4.650000 ( 4.649809)
Struct slow 0.090000 0.000000 0.090000 ( 0.094136)
Struct fast 0.080000 0.000000 0.080000 ( 0.078940)
两者的用例完全不同。
你可以把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
结构:
>> s = Struct.new(:a, :b).new(1, 2)
=> #<struct a=1, b=2>
>> s.a
=> 1
>> s.b
=> 2
>> s.c
NoMethodError: undefined method `c` for #<struct a=1, b=2>
OpenStruct:
>> require 'ostruct'
=> true
>> os = OpenStruct.new(a: 1, b: 2)
=> #<OpenStruct a=1, b=2>
>> os.a
=> 1
>> os.b
=> 2
>> os.c
=> nil
使用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.
推荐文章
- Rails:dependent =>:destroy VS:dependent =>:delete_all
- 我可以在不包含Ruby模块的情况下调用实例方法吗?
- 如何将新项目添加到哈希
- 测试一个Ruby类是否是另一个类的子类
- 什么时候使用Struct vs. OpenStruct?
- 数组到哈希Ruby
- 我如何让红宝石打印一个完整的回溯而不是截断一个?
- 如何使用RSpec的should_raise与任何类型的异常?
- 如何创建退出消息
- 忽略GEM,因为没有构建它的扩展
- 在Gem::Specification.reset期间未解决的规格:
- Delete_all vs destroy_all
- 双引号vs单引号
- 用any可以吗?'来检查数组是否为空?
- Rails获取“each”循环的索引