问题描述
例如,我有一个模块和一个类:
For example I have a module and a class:
module SimpleModule
def self.class_hello
puts "hello from #{@@name}"
end
end
class SimpleClass
@@name = 'StackOverFlow'
def self.test
SimpleModule.class_hello
end
end
然后我通过调用类中的模块方法进行测试:
Then I test by calling module method from class:
SimpleClass.test
我遇到例外:
我在这里知道是因为模块的作用域与类作用域不同.所以我的问题是:如何为SimpleModule范围共享SimpleClass范围?
I know here because scope of module is not same as class scope. So my question is: How can I share SimpleClass scope for SimpleModule scope?
我之所以使用元编程,是因为这只是一个简单的示例,此后,我将通过从动态类中调用动态模块来进行高级编程. (这就是为什么我不想使用某些关键字,例如 include 或 extend 的原因)
I put metaprogramming because here is just simple example, after that I will advanced by calling dynamic module from dynamic class. (that is the reason why I don't want to use some keyword such as include or extend)
@编辑实际上,我想自己实现Ruby扩展.这是我已经开发的版本:
@EditIn fact I want to implement Ruby extends on my own. Here is my already developed version:
# implementation
class Class
def custom_extend(module_name)
module_name.methods(false).each do |method|
define_singleton_method(method) do |*args, &block|
module_name.send(method, *args, &block)
end
end
end
end
这是我的自定义模块和测试类:
And here is my custom module and class for testing:
# -------------------------------------------------------------
# Demonstration
module SimpleModule
def self.class_hello_world
puts 'i am a simple module boss'
end
def self.class_hello_name
puts "hello from #{@@name}"
end
end
class SimpleClass
custom_extend SimpleModule
@@name = 'StackOverFlow'
end
这是我的两个测试:
SimpleClass.class_hello_world # work
SimpleClass.class_hello_name # not work
推荐答案
更新的答案
这是您的代码的稍作修改的版本.不需要include
,extend
,append_features
或module_function
.添加具有相同结构的custom_include
并不难.
Updated answer
Here's a slightly modified version of your code. No include
, extend
, append_features
or module_function
are needed. It wouldn't be hard to add custom_include
with the same structure.
更新:请务必阅读@ 7stud的答案,其结构相似且解释很好.
UPDATE: Make sure to read @7stud's answer, with a similar structure and very good explanation.
class Class
def custom_extend(module_name)
module_name.instance_methods(false).each do |method|
define_singleton_method(method) do |*args, &block|
module_name.instance_method(method).bind(self).call(*args, &block)
end
end
end
end
module SimpleModule
def class_hello
puts "hello from #{@name}"
end
end
class SimpleClass
@name = 'class'
custom_extend SimpleModule
def self.test
class_hello
end
end
SimpleClass.test
#=> hello from class
原始答案
常规方式
通常的方法是:
Original answer
Usual way
The usual way would be :
module SimpleModule
def class_hello
puts "hello from #{@name}"
end
end
class SimpleClass
@name = 'StackOverFlow'
extend SimpleModule
def self.test
class_hello
end
end
SimpleClass.class_hello
但是您不想要它. (为什么?)
but you don't want it. (why?)
在您的代码中,SimpleClass
和SimpleModule
彼此完全独立.很明显,您得到了NameError
.您需要以某种方式传递name
信息.
In your code, SimpleClass
and SimpleModule
are totally independent from one another. It's clear that you get a NameError
. You need to somehow pass the name
information.
module SimpleModule
def self.class_hello(name='')
puts "hello from #{name}"
end
end
class SimpleClass
@@name = 'StackOverFlow'
def self.test
SimpleModule.class_hello(@@name)
end
end
带有klass参数:
module SimpleModule
def self.class_hello(calling_class=self)
calling_class.class_eval{
puts "hello from #{@name}"
}
end
end
class SimpleClass
@name = 'StackOverFlow'
def self.test
SimpleModule.class_hello(self)
end
end
SimpleClass.test
使用binding
参数:
With binding
parameter :
module SimpleModule
def self.class_hello(b)
puts "hello from #{b.eval('@@name')}"
end
end
class SimpleClass
@@name = 'StackOverFlow'
def self.test
SimpleModule.class_hello(binding)
end
end
SimpleClass.test
使用my_ruby_extend SimpleModule
当然可以使用自定义的my_ruby_extend
完成.不过,您需要显示所需的语法以及已经实现的内容.
With my_ruby_extend SimpleModule
It surely can be done with a custom my_ruby_extend
. You'd need to show the desired syntax though, and what you already implemented.
这样,您可以告诉Ruby SimpleClass
和SimpleModule
是链接的.如果在SimpleModule
中找不到方法或变量,则可以在SimpleClass
中进行查找.
This way, you could tell Ruby that SimpleClass
and SimpleModule
are linked. When a method or a variable isn't found in SimpleModule
, it could be sought in SimpleClass
.
这篇关于Ruby元编程:如何使模块方法看到类的变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!