一般来说,与Struct相比,使用OpenStruct的优点和缺点是什么?什么样类型的通用用例适合每一个?
当前回答
两者的用例完全不同。
你可以把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
其他回答
其他指标:
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
与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的内存。
使用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
推荐文章
- 是否可以在MiniTest中运行单个测试?
- 如何在Ruby中生成a和b之间的随机数?
- 无法安装gem -未能建立gem本地扩展-无法加载这样的文件——mkmf (LoadError)
- 如何在Ruby中创建文件
- 什么是Ruby文件。开放模式和选项?
- Ruby数组到字符串的转换
- 如何分割(块)一个Ruby数组成X元素的部分?
- Ruby中“or”和||的区别?
- 如何测试参数是否存在在轨道
- 在Ruby中不创建新字符串而修饰字符串的规范方法是什么?
- RVM不是一个函数,用' RVM use…’不会起作用
- 了解Gemfile。锁文件
- 如何确定一个数组是否包含另一个数组的所有元素
- 是什么导致这个ActiveRecord::ReadOnlyRecord错误?
- 最好的打印散列的方法