请考虑以下代码:
module MyClass
def foo
"method"
end
end
现在,我可以通过常规
实例化一个新类@my_new_class = MyClass.new
或者,我可以做一些元编程魔术
@my_new_class = Class.new { include MyClass }.send :new
问题是两者之间有什么区别?
答案 0 :(得分:4)
上面的代码(几乎)等同于:
MyNewClass = Class.new { include MyClass }
@my_new_class = MyNewClass.new
这就像
class MyNewClass
include MyClass
end
@my_new_class = MyNewClass.new
使用Class.new
即时声明匿名新类:
使用给定的超类创建一个新的匿名(未命名)类(如果没有给出参数,则创建Object)。您可以通过将类对象赋值给常量来为类赋予名称。
如果给出了一个块,它将传递给该类对象,并使用
class_eval
在该类的上下文中计算该块。
答案 1 :(得分:1)
您对该模块的命名类似于sue = Boy.new
,因此我已将其更改为适合其遗产。我相信你不会介意。
module MyModule
def foo
"method"
end
end
让我们先收集一些基本信息:
Module.class #=> Class
Module.ancestors #=> [Module, Object, Kernel, BasicObject]
Module.methods.include? :new #=> true
Module.new #=> #<Module:0x000001022050c8>
如您所见,Module
是Class
的一个实例,其方法为:new
。现在让我们看看你创建的模块:
MyModule.class #=> Module
MyModule.ancestors #=> [MyModule]
MyModule.instance_methods #=> [:foo]
MyModule.methods.include? :new #=> false
它是Class
的一个实例,只有一个实例方法(:foo
),您创建了它。它没有祖先,所以它不会继承任何方法。重要的是,Module
的实例没有方法:new
。因此,如果我们尝试调用它,结果是可预测的:
my_new_module = MyModule.new
#=> NoMethodError: undefined method `new' for MyModule:Module
方法#1的故事结束。
现在收集与您的第二种方法相关的信息:
my_new_instance = Class.new { include MyModule }.send :new
我已将变量my_new_class
的名称更改为my_new_instance
,原因很快就会显现出来。我们可以分两步编写,如下所示:
Class1 = Class.new { include MyModule }
Class1.instance_methods.include? :foo #=> true
Class1.methods.include? :new #=> true
Class1.method(:new).owner #=> Class
因此,我们确认Class1
已正确构建,具有实例方法:foo
并从:new
继承了类方法Class
。
my_new_instance = Class1.new #=> #<Class1:0x00000101a1edc8>
my_new_instance = Class1.send :new #=> #<Class1:0x0000010204eab8>
my_new_instance.class #=> Class1
my_new_instance.is_a? Class #=> false
my_new_instance.foo # (prints) "method"
my_new_instance.send :foo # (prints) "method"
我们看到my_new_instance
确实是Class1
的一个实例(可以通过所示的任一方法创建),并以所示的两种方式之一调用:foo
。< / p>