為了在類和類實體之間共享資料,ActiveSupport 有很棒的方法class_attribute。例如
require 'active_support/core_ext/class/attribute.rb'
# Step 1: declare a class record and implement class_attribute :fields.
# We can use it to declare attr_accessor
class Record
class_attribute :fields
self.fields = [:id]
def self.attribute(new_field_name)
self.fields = fields | [new_field_name]
instance_eval do
attr_accessor new_field_name
end
end
end
# Step 2: Declare class Topic with two attributes
class Topic < Record
attribute :title
attribute :body
end
# Step 3: Declare another class user with other two attributes
# And one more class with addition attribute
class User < Record
attribute :first_name
attribute :last_name
end
# Step 4: Let's check.
# Each class has it own attributes and data is shared between class and instances
puts Topic.fields
# [:id, :title, :body]
puts Topic.new.fields
# [:id, :title, :body]
puts User.fields
# [:id, :first_name, :last_name]
puts User.new.fields
# [:id, :first_name, :last_name]
我寫了一個小紅寶石腳本,不想對 ActiveSupport 有額外的依賴。另外,我不能使用類變數(帶有“@@”的變數),因為更改子類的值會影響父類。
作為選項 - 我可以將 class_attribute 源代碼復制并粘貼到我的 Ruby 腳本中,但我很想在純 Ruby 中找到解決方案??
沒有人可以幫助我或就如何在純 Ruby 上輕松實作它提供建議嗎?
uj5u.com熱心網友回復:
也許attr_accessor為類實體變數定義一個,然后將所需的實體方法轉發給類上的那些方法?
require 'forwardable'
class Foo
extend Forwardable
class << self
attr_accessor :fields
end
def_delegator self, :fields
def_delegator self, :fields=
end
foo = Foo.new
p Foo.fields #=> nil
p foo.fields #=> nil
Foo.fields = { set_on: 'Class' }
p foo.fields #=> {:set_on=>"Class"}
foo.fields = { set_on: 'instance' }
p Foo.fields #=> {:set_on=>"instance"}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/447707.html
下一篇:描述php物件
