[英]Ruby: Do something when extending an instance with a module
I'd like to execute some code when an instance is extended with Object#extend .当使用Object#extend 扩展实例时,我想执行一些代码。 A bit like
initialize
when instantiating a class but for a module.有点像实例化类时的
initialize
,但用于模块。
Here is the extended 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"
For example I'd like to display a warning or raise if Mod
is used to extend
something else than an instance of GoodKlass
:例如,如果
Mod
用于extend
GoodKlass
实例以外的其他内容,我想显示警告或加注:
bad = BadKlass.new
bad.extend(Mod) #=> raise "Mod cannot extend BadKlass"
You can define self.extended in the module:您可以在模块中定义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
Your comment on the question, replying to my comment, confirmed a suspicion I had.你对这个问题的评论,对我的评论的回复,证实了我的怀疑。 What you have done is not to extend the class, but to extend a particular instance of the class.
您所做的不是扩展类,而是扩展类的特定实例。 Let's see what your code does.
让我们看看你的代码做了什么。
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"
As you see, hello
is only defined on the instance good
.如您所见,
hello
仅在实例good
上定义。
Note笔记
GoodKlass.methods.include?(:hello) #=> false
good.methods.include?(:hello) #=> true
If that's not what you want, there are two possibilities.如果这不是您想要的,则有两种可能性。 I reference
我参考
class VeryGoodKlass
end
in discussing both.在讨论两者。
1. Extend
the class 1.
Extend
类
In your application (ref comments on the question), this approach would allow you to a create a class method File::jpg?
在您的应用程序中(对问题的引用评论),这种方法将允许您创建一个类方法
File::jpg?
which would be invoked File.jpeg?("cat.jpg")
.这将被调用
File.jpeg?("cat.jpg")
。
To convert Mod
's instance method hello
to a class method of GoodKlass
you need to extend the class (not an instance of the class), using Object#extend .要将
Mod
的实例方法hello
转换为GoodKlass
的类方法,您需要使用Object#extend扩展类(不是类的实例)。 To prevent other classes from extending the module, use the callback method Module#extended in the module.要防止其他类扩展模块,请在模块中使用回调方法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. Include the module in the class 2.在类中包含模块
To add Mod
's instance methods to GoodKlass
(keeping them instance methods) you need to include the module, using Module#include .要将
Mod
的实例方法添加到GoodKlass
(保留它们的实例方法),您需要使用Module#include包含该模块。 To prevent other classes from including the module, use the callback method #included in the module.要防止其他类包含该模块,请在模块中使用回调方法#included 。
In your application this would allow you to write an instance method File#jpg?
在您的应用程序中,这将允许您编写一个实例方法
File#jpg?
1 used as follows: 1使用如下:
f = File.new('cat.jpg')
f.jpg?
You could do that as follows.您可以按如下方式执行此操作。
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. Perhaps File.basename(f.path).end_with?(".jpg")
. 1. 也许
File.basename(f.path).end_with?(".jpg")
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.