I know, I can overwrite class method from module this way
我知道,我可以用这种方式覆盖模块中的类方法
class Foo
class << self
def some_static_method
puts 'some_static_method'
end
end
end
module BAR
class << Foo
def some_static_method
puts 'another_static_method'
end
end
end
class Foo
include BAR
end
Foo.some_static_method # => 'another_static_method'
Is it possible for an instance method?
实例方法有可能吗?
3 个解决方案
#1
1
You can do the following:
您可以执行以下操作:
class Foo
def self.some_static_method; puts "Hello from Foo" end
end
module Bar
def self.included(base)
base.instance_eval do
def some_static_method; puts "Hello from Bar" end
end
end
end
class Foo
include Bar
end
Foo.some_static_method
This should work
这应该工作
UPDATE
UPDATE
To override instance method use:
要覆盖实例方法,请使用:
class Foo
def some_instance_method; puts "Hello from Foo" end
end
module Bar
def self.included(base)
base.class_eval do
def some_instance_method; puts "Hello from Bar" end
end
end
end
class Foo
include Bar
end
Foo.new.some_instance_method
#2
1
Your question is actually not about method overriding. It is about what class is referred to within a class ...
construction in a module body.
你的问题实际上不是方法覆盖。它是关于在类中引用的类...模块体中的构造。
When you do
当你这样做
module Bar
class << Foo
p self
end
end
# => #<Class:Foo>
the << Foo
points to the singleton class of the Foo
in the main environment because class << Foo
cannot define the singleton class directly of a class Foo
that has not been defined in advance. So it looks up for Foo
that is already defined, and such class is found in the main environment.
<< Foo指向主环境中Foo的单例类,因为类<< Foo无法直接定义未预先定义的类Foo的单例类。所以它查找已经定义的Foo,并且在主环境中找到这样的类。
When you do
当你这样做
module Bar
class Foo
p self
end
end
# => Bar::Foo
a new class Bar::Foo
is created; the Foo
points to this Bar::Foo
that is newly created, and it does not point to the Foo
in the main environment. In order to point to it, you have to explicitly specify that with ::
.
创建了一个新类Bar :: Foo; Foo指向新创建的Bar :: Foo,它并不指向主环境中的Foo。为了指向它,你必须用::显式指定。
module Bar
class ::Foo
p self
end
end
# => Foo
#3
1
If you are using Ruby > 2.0.0 then what you can use is Module#prepend
. Instead of include
you can prepend
an module and that way all of the module's methods are overriding any existing class instance methods with the same name. You can see a quick example here.
如果您使用的是Ruby> 2.0.0,那么您可以使用的是Module #prepend。而不是包含你可以预先添加一个模块,这样所有模块的方法都覆盖任何具有相同名称的现有类实例方法。你可以在这里看到一个简单的例子。
Prior to Ruby 2, Rails had introduced a similar hack: #alias_method_chain
在Ruby 2之前,Rails引入了类似的hack:#alias_method_chain
Here is a nice comparison of the two approaches.
这是两种方法的比较。
#1
1
You can do the following:
您可以执行以下操作:
class Foo
def self.some_static_method; puts "Hello from Foo" end
end
module Bar
def self.included(base)
base.instance_eval do
def some_static_method; puts "Hello from Bar" end
end
end
end
class Foo
include Bar
end
Foo.some_static_method
This should work
这应该工作
UPDATE
UPDATE
To override instance method use:
要覆盖实例方法,请使用:
class Foo
def some_instance_method; puts "Hello from Foo" end
end
module Bar
def self.included(base)
base.class_eval do
def some_instance_method; puts "Hello from Bar" end
end
end
end
class Foo
include Bar
end
Foo.new.some_instance_method
#2
1
Your question is actually not about method overriding. It is about what class is referred to within a class ...
construction in a module body.
你的问题实际上不是方法覆盖。它是关于在类中引用的类...模块体中的构造。
When you do
当你这样做
module Bar
class << Foo
p self
end
end
# => #<Class:Foo>
the << Foo
points to the singleton class of the Foo
in the main environment because class << Foo
cannot define the singleton class directly of a class Foo
that has not been defined in advance. So it looks up for Foo
that is already defined, and such class is found in the main environment.
<< Foo指向主环境中Foo的单例类,因为类<< Foo无法直接定义未预先定义的类Foo的单例类。所以它查找已经定义的Foo,并且在主环境中找到这样的类。
When you do
当你这样做
module Bar
class Foo
p self
end
end
# => Bar::Foo
a new class Bar::Foo
is created; the Foo
points to this Bar::Foo
that is newly created, and it does not point to the Foo
in the main environment. In order to point to it, you have to explicitly specify that with ::
.
创建了一个新类Bar :: Foo; Foo指向新创建的Bar :: Foo,它并不指向主环境中的Foo。为了指向它,你必须用::显式指定。
module Bar
class ::Foo
p self
end
end
# => Foo
#3
1
If you are using Ruby > 2.0.0 then what you can use is Module#prepend
. Instead of include
you can prepend
an module and that way all of the module's methods are overriding any existing class instance methods with the same name. You can see a quick example here.
如果您使用的是Ruby> 2.0.0,那么您可以使用的是Module #prepend。而不是包含你可以预先添加一个模块,这样所有模块的方法都覆盖任何具有相同名称的现有类实例方法。你可以在这里看到一个简单的例子。
Prior to Ruby 2, Rails had introduced a similar hack: #alias_method_chain
在Ruby 2之前,Rails引入了类似的hack:#alias_method_chain
Here is a nice comparison of the two approaches.
这是两种方法的比较。