[英]Ruby: Do something when extending an instance with a module
当使用Object#extend 扩展实例时,我想执行一些代码。 有点像实例化类时的initialize
,但用于模块。
这是扩展文档示例:
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"
您可以在模块中定义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
你对这个问题的评论,对我的评论的回复,证实了我的怀疑。 您所做的不是扩展类,而是扩展类的特定实例。 让我们看看你的代码做了什么。
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
类
在您的应用程序中(对问题的引用评论),这种方法将允许您创建一个类方法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")
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.