本文简要介绍ruby语言中 OpenStruct类
的用法。
OpenStruct
是一种数据结构,类似于 Hash
,它允许定义任意属性及其伴随值。这是通过使用 Ruby 的元编程在类本身上定义方法来实现的。
例子
require "ostruct"
person = OpenStruct.new
person.name = "John Smith"
person.age = 70
person.name # => "John Smith"
person.age # => 70
person.address # => nil
OpenStruct
在内部使用 Hash
来存储属性和值,甚至可以用一个初始化:
australia = OpenStruct.new(:country => "Australia", :capital => "Canberra")
# => #<OpenStruct country="Australia", capital="Canberra">
Hash
带有空格或字符的键通常不能用于方法调用(例如 ()[]*
)将不会立即在 OpenStruct
对象上作为检索或分配方法可用,但仍可以通过 Object#send
方法或使用 []。
measurements = OpenStruct.new("length (in inches)" => 24)
measurements[:"length (in inches)"] # => 24
measurements.send("length (in inches)") # => 24
message = OpenStruct.new(:queued? => true)
message.queued? # => true
message.send("queued?=", false)
message.queued? # => false
删除属性的存在需要执行 delete_field
方法,因为将属性值设置为 nil
不会删除该属性。
first_pet = OpenStruct.new(:name => "Rowdy", :owner => "John Smith")
second_pet = OpenStruct.new(:name => "Rowdy")
first_pet.owner = nil
first_pet # => #<OpenStruct name="Rowdy", owner=nil>
first_pet == second_pet # => false
first_pet.delete_field(:owner)
first_pet # => #<OpenStruct name="Rowdy">
first_pet == second_pet # => true
Ractor
兼容性:具有可共享值的冻结 OpenStruct
本身是可共享的。
注意事项
OpenStruct
利用 Ruby 的方法查找结构来查找和定义属性的必要方法。这是通过method_missing 和define_singleton_method 方法完成的。
如果担心所创建对象的性能,这应该是一个考虑因子,因为与使用 Hash
或 Struct
相比,设置这些属性的开销要大得多。从一个小的 Hash
创建一个开放结构并访问一些条目可能比直接访问散列慢 200 倍。
这是一个潜在的安全问题;从不受信任的用户数据(例如 JSON
Web 请求)构建 OpenStruct
可能容易受到“符号拒绝服务”攻击,因为 key 创建方法和方法名称永远不会被垃圾收集。
这也可能是 Ruby 版本之间不兼容的根源:
o = OpenStruct.new
o.then # => nil in Ruby < 2.6, enumerator for Ruby >= 2.6
内置方法可能会以这种方式被覆盖,这可能是错误或安全问题的根源:
o = OpenStruct.new
o.methods # => [:to_h, :marshal_load, :marshal_dump, :each_pair, ...
o.methods = [:foo, :bar]
o.methods # => [:foo, :bar]
为了帮助解决冲突, OpenStruct
仅使用以 !
结尾的受保护/私有方法,并通过添加 !
为内置公共方法定义别名:
o = OpenStruct.new(make: 'Bentley', class: :luxury)
o.class # => :luxury
o.class! # => OpenStruct
建议(但不强制)不要使用以 !
结尾的字段;请注意,子类的方法不能被覆盖,OpenStruct 自己的以 !
结尾的方法也不能被覆盖。
由于所有这些原因,请考虑完全不使用 OpenStruct
。
相关用法
- Ruby OpenStruct.ostruct[name] =用法及代码示例
- Ruby OpenStruct.==用法及代码示例
- Ruby OpenStruct.each_pair用法及代码示例
- Ruby OpenStruct.delete_field用法及代码示例
- Ruby OpenStruct.dig用法及代码示例
- Ruby OpenStruct.new用法及代码示例
- Ruby OpenStruct.ostruct[name]用法及代码示例
- Ruby OpenSSL.fips_mode =用法及代码示例
- Ruby OpenSSL模块用法及代码示例
- Ruby OpenSSL.print_mem_leaks用法及代码示例
- Ruby OpenSSL.Digest用法及代码示例
- Ruby Open3.capture3用法及代码示例
- Ruby Open3.capture2用法及代码示例
- Ruby Open3.capture2e用法及代码示例
- Ruby Open3.popen2e用法及代码示例
- Ruby OpenRead.open用法及代码示例
- Ruby Open3.popen3用法及代码示例
- Ruby Open3.popen2用法及代码示例
- Ruby Open3.pipeline用法及代码示例
- Ruby OpenURI模块用法及代码示例
- Ruby Open3.pipeline_rw用法及代码示例
- Ruby Open3.pipeline_w用法及代码示例
- Ruby Open3.pipeline_r用法及代码示例
- Ruby Open3.pipeline_start用法及代码示例
- Ruby Option.level用法及代码示例
注:本文由纯净天空筛选整理自ruby-lang.org大神的英文原创作品 OpenStruct类。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。