本帖最后由 taroxd 于 2015-9-15 16:29 编辑
在较新版本的 Ruby 中:
C = Class.new class C < C.clone # 这里是打开 C 而不是覆盖常量 C,而 C.clone 不是原来 C 的父类 Object,因此会报错 end # superclass mismatch for class C (TypeError)
C = Class.new
class C < C.clone # 这里是打开 C 而不是覆盖常量 C,而 C.clone 不是原来 C 的父类 Object,因此会报错
end
# superclass mismatch for class C (TypeError)
所以,要用这种方式的话,应该是这样的代码
class C def c 1 end end class C < Object.send :remove_const, :C def c super + 1 end end
class C
def c
1
end
end
class C < Object.send :remove_const, :C
def c
super + 1
end
end
然而这种方式不仅会让继承链变得很难看,而且很容易导致问题。
class Game_BattlerBase # 默认脚本 end class Game_Battler < Game_BattlerBase # 默认脚本 end # 若这一行是 # class Game_BattlerBase < Object.send :remove_const, :Game_BattlerBase # 也一样会导致问题 class Game_Battler < Object.send :remove_const, :Game_Battler # A 的插件脚本 end class Game_Battler < Game_BattlerBase # B 的插件脚本 end # superclass mismatch for class Game_Battler (TypeError)
class Game_BattlerBase
# 默认脚本
end
class Game_Battler < Game_BattlerBase
# 默认脚本
end
# 若这一行是
# class Game_BattlerBase < Object.send :remove_const, :Game_BattlerBase
# 也一样会导致问题
class Game_Battler < Object.send :remove_const, :Game_Battler
# A 的插件脚本
end
class Game_Battler < Game_BattlerBase
# B 的插件脚本
end
# superclass mismatch for class Game_Battler (TypeError)
很明显,这个脚本冲突就是 A 的锅
不想发生命名冲突的话,应该是这样的方式比较好
class C def c 1 end end class C original_c = instance_method :c define_method :c do original_c.bind(self).call + 1 end end
class C
def c
1
end
end
class C
original_c = instance_method :c
define_method :c do
original_c.bind(self).call + 1
end
end
接着推销一下这个:http://taroxd.github.io/rgss/Tar ... AE%BE%E7%BD%AE.html
当然,还是更高版本 Ruby 中的 prepend 和 refine 最舒服。
class C def c 1 end end module MyPatchToC def c super + 1 end end C.prepend MyPatchToC
class C
def c
1
end
end
module MyPatchToC
def c
super + 1
end
end
C.prepend MyPatchToC
# 在我自己的脚本里,我就直接把 id 猴补到 Fixnum 里面了。 # 为了在某些场合既能传物品(装备、角色等等)id作为参数,也能传入物品的实例作为参数 # 其实我挺希望能这样用 refine 的 module MyPatchToFixnum refine Fixnum do alias_method :id, :to_int end end class AnotherClass using MyPatchToFixnum def self.show(item_or_item_id) puts item_or_item_id.id end end # assume that $data_items exists AnotherClass.show($data_items[1]) # 1 AnotherClass.show(1) # 1 1.id # undefined method `id' for 1:Fixnum (NoMethodError)
# 在我自己的脚本里,我就直接把 id 猴补到 Fixnum 里面了。
# 为了在某些场合既能传物品(装备、角色等等)id作为参数,也能传入物品的实例作为参数
# 其实我挺希望能这样用 refine 的
module MyPatchToFixnum
refine Fixnum do
alias_method :id, :to_int
end
end
class AnotherClass
using MyPatchToFixnum
def self.show(item_or_item_id)
puts item_or_item_id.id
end
end
# assume that $data_items exists
AnotherClass.show($data_items[1]) # 1
AnotherClass.show(1) # 1
1.id # undefined method `id' for 1:Fixnum (NoMethodError)
以及,如果不是做 RM 插件的话,这种技术的实际应用真的很少…… |