當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


Ruby OpenStruct類用法及代碼示例


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