我正在构建一个类似于ActiveRecord的特定于域的层次结构继承结构,即我有一个Base
类,然后在n
下声明了Base
个子类。
我目前正在将子项中的细节声明为常量,然后从Base
类中的共享方法中调用它们,但它变得笨拙。我想通过方法调用实现Rails样式来声明特定于类的实例化值。
如果您熟悉Rails,我实际上是在尝试从ActiveRecord复制has_many
/ belongs_to
的通用结构,或者从ActionPack复制before_action
。
我想要完成的一个简单的,人为的例子......
class Widget < Base
important_value :foo, :bar
end
widget = Widget.new
widget.foo
# => :bar
如果有人可以向我解释在课程Base
中要实现上述目标的内容,我将会顺利开展。
答案 0 :(得分:1)
class Base
class << self
def important_value(key, value)
# define method named `key` which returns `value`
define_method(key) { value }
end
end
end
class Widget < Base
important_value :foo, :bar
end
Widget.new.foo # => :bar
或者,如果“重要值”方法的数量很少且事先已知:
class Base
def foo
self.class.foo
end
class << self
attr_reader :foo
def important_value(key, value)
self.instance_variable_set(:"@#{key}", value)
end
end
end
class Widget < Base
important_value :foo, :bar
end
Widget.new.foo # => :bar
答案 1 :(得分:0)
这与我原来问题的条件并不完全一致,但它对我的推动非常有帮助。
class Base
# defining variables happens at the class level
# the first line allows us to set a sane default (skip for a nil value)
# the second line makes the method a getter as well as a setter (this is required)
def self.title(val = nil)
@title ||= 'DEFAULT TITLE'
return @title if val.nil?
@title = val.upcase
end
# the instance-level reader
# if you want to change the values from the child, use attr_accessor
# in either case, the visibility of @title in the child is unchanged (we assume its not accessed directly)
attr_reader :title
# set the instance variable when the class is instantiated
def initialize
instance_variable_set("@title", self.class.title)
end
end
class Foo < Base
title "foo title"
end
class Bar < Base
# if left commented out, the value will be set to 'DEFAULT TITLE'
# title "BAR TITLE"
end
f = Foo.new
f.title
# => "FOO TITLE"
b = Bar.new
b.title
# => "DEFAULT TITLE"