您定義的方法initialize
調用old_initialize
,但你alias_method
它old_initialize
,所以old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
會打電話old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
將調用old_initialize
...
我寫了一個相當長的有關「正確」的方式稱爲舊版本的覆蓋方法的文章here:
這樣做的最好方法就是根本就不這樣做。不要覆蓋方法,重寫它們。所以他們得到適當的名稱,並修改API,使人們可以一氣呵成創建多個訪問
class Module
def custom_attr_accessor(attr)
attr_reader attr
prepend(Module.new do
define_method(:initialize) do |*args|
super(*args)
instance_variable_set(:"@#{attr}", yield)
end
end)
end
end
class Foo
custom_attr_accessor :foo do 'foo' end
custom_attr_accessor :bar do 'bar' end
end
# It works:
Foo.new
# => #<Foo:0xdeadbeef081542 @foo='foo', @bar='bar'>
# How it works:
Foo.ancestors
# => [#<Module:0xdeadbeef081523>,
# #<Module:0xdeadbeef081524>,
# Foo,
# Object,
# Kernel,
# BasicObject]
我們可以讓這個更好一點通過分配混入常量:Ruby有繼承性,用它
class Module
def custom_attr_accessor(attr=(no_attr = true), **attr_specs, &blk)
attr_specs[attr] = blk unless no_attr
attr_specs.each do |attr, blk|
attr_reader attr
prepend CustomAttrAccessor.(attr, &blk)
end
end
end
module CustomAttrAccessor
def self.call(attr)
m = Module.new do
define_method(:initialize) do |*args|
super(*args)
instance_variable_set(:"@#{attr}", yield)
end
end
const_set(:"CustomAttrAccessor_#{attr}_#{m.object_id}", m)
end
end
class Foo
custom_attr_accessor :foo do 'foo' end
custom_attr_accessor :bar do 'bar' end
end
# It works:
Foo.new
# => #<Foo:0xdeadbeef081542 @foo='foo', @bar='bar'>
# How it works:
Foo.ancestors
# => [CustomAttrAccessor::CustomAttrAccessor_bar_48151623420020,
# CustomAttrAccessor::CustomAttrAccessor_foo_48151623420010,
# Foo,
# Object,
# Kernel,
# BasicObject]
class Bar
custom_attr_accessor :foo do 'FOO' end
custom_attr_accessor :bar do 'BAR' end
custom_attr_accessor baz: -> { 'BAZ' }, qux: -> { 'QUX' }
end
# It works:
Bar.new
# => #<Bar:0xdeadbeef081542 @foo='FOO', @bar='BAR' @baz='BAZ', @qux='QUX'>
# How it works:
Bar.ancestors
# => [CustomAttrAccessor::CustomAttrAccessor_qux_48151623420060,
# CustomAttrAccessor::CustomAttrAccessor_baz_48151623420050,
# CustomAttrAccessor::CustomAttrAccessor_bar_48151623420040,
# CustomAttrAccessor::CustomAttrAccessor_foo_48151623420030,
# Bar,
# Object,
# Kernel,
# BasicObject]
請記住,在這種情況下' 「#{} ATTR」'相當於減少混亂'attr'。 – tadman