我希望在使用Object#extend扩展实例时执行一些代码。在实例化一个类但是为一个模块时有点像initialize
。
这是扩展的documentation example:
module Mod
def hello
"Hello from Mod.\n"
end
end
class GoodKlass
def hello
"Hello from GoodKlass.\n"
end
end
class BadKlass
# something totally different
end
good = GoodKlass.new
good.hello #=> "Hello from GoodKlass.\n"
good.extend(Mod) #=> #<GoodKlass:0x401b3bc8>
good.hello #=> "Hello from Mod.\n"
例如,如果Mod
用于extend
而不是GoodKlass
的实例,我希望显示警告或加注:
bad = BadKlass.new
bad.extend(Mod) #=> raise "Mod cannot extend BadKlass"
答案 0 :(得分:3)
您可以在模块中定义self.extended:
module Mod
def self.extended(base)
raise "Cannot extend #{base}" unless base.is_a?(GoodKlass)
end
def hello
"Hello from Mod.\n"
end
end
答案 1 :(得分:1)
你对这个问题的评论,回复我的评论,证实了我的怀疑。你所做的不是扩展类,而是扩展类的特定实例。让我们看看你的代码做了什么。
good = GoodKlass.new
good.hello #=> "Hello from GoodKlass.\n"
GoodKlass.hello #=> NoMethodError: undefined method `hello' for GoodKlass:Class
good.extend(Mod)
GoodKlass.hello #=> NoMethodError: undefined method `hello' for GoodKlass:Class
good.hello #=> "Hello from Mod.\n"
very_good = GoodKlass.new
very_good.hello #=> "Hello from GoodKlass.\n"
如您所见,hello
仅在实例good
上定义。
请注意
GoodKlass.methods.include?(:hello) #=> false
good.methods.include?(:hello) #=> true
如果那不是你想要的,有两种可能性。我参考了
class VeryGoodKlass
end
讨论两者。
1。 Extend
班级
在您的应用程序中(对该问题的ref评论),这种方法可以让您创建一个可以调用File::jpg?
的类方法File.jpeg?("cat.jpg")
。
要将Mod
的实例方法hello
转换为GoodKlass
的类方法,您需要使用Object#extend扩展类(不是类的实例) 。要防止其他类扩展模块,请使用模块中的回调方法Module#extended。
module Mod
def self.extended(base)
raise ArgumentError, "Cannot extend #{base}" unless base == GoodKlass
end
def hello
"Hello from Mod"
end
end
class GoodKlass
def self.hello
"Hello from GoodKlass"
end
end
GoodKlass.hello #=> "Hello from GoodKlass"
GoodKlass.extend(Mod)
GoodKlass.hello #=> "Hello from Mod"
VeryGoodKlass.extend(Mod) #=> ArgumentError: Cannot extend VeryGoodKlass
2。在课程中包含该模块
要将Mod
的实例方法添加到GoodKlass
(保留它们的实例方法),您需要使用Module#include包含该模块。要防止其他类包含模块,请在模块中使用回调方法#included。
在你的应用程序中,这将允许你编写一个实例方法File#jpg?
1 ,如下所示:
f = File.new('cat.jpg')
f.jpg?
你可以这样做。
module Mod
def self.included(base)
raise ArgumentError, "Cannot include #{base}" unless base == GoodKlass
end
def hello
"Hello"
end
end
class GoodKlass
end
good = GoodKlass.new
GoodKlass.include(Mod)
GoodKlass.hello #=> NoMethodError: undefined method `hello' for GoodKlass:Class
good.hello #=> "Hello"
VeryGoodKlass.include(Mod) #=> ArgumentError: Cannot include VeryGoodKlass
1。也许是File.basename(f.path).end_with?(".jpg")
。