本文簡要介紹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類。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。