前田です。
前もちょっと考えたのですが
attr :foo, TRUE, "default value"
としたいと思って試してみました。
---------------------
1).
module AttrInitMixinE
def AttrInitMixinE.extend_object(klass)
result = super(klass)
klass.module_eval 'ATTR_DEFAULTS = Hash.new'
return result
end
def attr(name, writable = FALSE, default = nil)
result = super(name, writable)
if name.instance_of? Fixnum
name = name.id2name
end
self::ATTR_DEFAULTS[name] = default
return result
end
def new(*args)
result = super
result.instance_eval %q[
ATTR_DEFAULTS.each do |name, default|
eval "@#{name} = default"
end
]
return result
end
end
class Foo
extend AttrInitMixinE
attr :foo, TRUE, "default value"
end
---------------------
2).
module AttrInitMixinI
def AttrInitMixinI.append_features(klass)
result = super(klass)
klass.module_eval %q{
ATTR_DEFAULTS = Hash.new
def klass.attr(name, writable = FALSE, default = nil)
super(name, writable)
if name.instance_of? Fixnum
name = name.id2name
end
ATTR_DEFAULTS[name] = default
end
}
return result
end
def initialize(*args)
super
type::ATTR_DEFAULTS.each do |name, default|
eval "@#{name} = default"
end
end
end
class Foo
include AttrInitMixinI
attr :foo, TRUE, "default value"
end
---------------------
1はextendするパターンで2はincludeするパターンです。
モジュールのユーザーにとって,1のようにクラスをextendするのは
ちょっとわかりにくいのかなと思うのですが,どうなんでしょう。
# 石塚さんはクラスのextendを多用されていそうですが(^^;
でも2だとappend_featuresの中でメソッド定義しているのがちょっと
苦しげですし,1.1でしか動きませんよね。
で,ここからが本題です。
includeで特異メソッドも継承されると,2みたいなのをもっときれい
に書けると思うのですが,includeで特異メソッドが継承されないの
はなぜでしょう。普通の継承では特異メソッドも継承されるのでinclude
でも継承されるとうれしいのですが,やはり何か問題があるのでしょうか。
1)のattrではself::ATTR_DEFAULTS,2)のinitializeではtype::ATTR_DEFAULTS
としないとNameErrorになるのですが,これはこういうものなのでしょうか。
--
前田 修吾