读了一些自己在ruby中使用的代码,仍然不能理解一些例子:
class A
def hi
"hi"
end
def self.hello
"hello"
end
end
a=A.new
a.hi
A.hello
我明白我可以用下面的方法来改变示例方法定义:
class << a
def hi
"hi from a <<"
end
end
a.hi => "hi from a <<"
但这是什么
class << a
def self.hello
"H E L L O"
end
end
[21] pry(main)> A.hello
=> "hello"
[22] pry(main)> a.hello
<<ERROR1>> NoMethodError: undefined method `hello' for #<A:0x007fe41338ecb8>
我也不确定我到底在做什么。
和定义的区别是什么
class << a
def hi
"hi from a <<"
end
end
and
class << A
def hi
"hi from a <<"
end
end
?
class A
p "in class A: #{self}, type: #{self.class}"
def f
p "in f: #{self}, type: #{self.class}"
end
def self.m
p "in selfm: #{self}, type: #{self.class}"
end
end
metaclass = class << a;self;end
metaclass.instance_eval do
"hi : #{self}, type: #{self.class}"
def f7
"in f7 .. : #{self}, type: #{self.class}"
end
def self.f9
"in f7 .. : #{self}, type: #{self.class}"
end
end
A.f7
a.f7
A.f9
a.f9
<<ERROR2>>
[20]查询(主)〉A.f9无方法错误:未定义的方法f9' for A:Class from (pry):40:in
pry'[21] pry(main)〉a.f9无方法错误:未定义的方法f9' for #<A:0x007fb70717c0d0> from (pry):41:in
pry'
<<ERROR3>>
[22]查询(主)〉[23]查询(主)〉A.f7无方法错误:未定义的方法f7' for A:Class from (pry):42:in
pry'[24] pry(main)〉a.f7无方法错误:未定义的方法f7' for #<A:0x007fb70717c0d0> from (pry):43:in
pry'[25] pry(main)〉A.f9无方法错误:未定义的方法f9' for A:Class from (pry):44:in
pry'[26] pry(main)〉a.f9无方法错误:未定义的方法f9' for #<A:0x007fb70717c0d0> from (pry):45:in
pry'
您能否帮助指出这些错误究竟是什么:参考〈〉标记
1.看到〈〉,我的问题:
在一个对象中定义self.method有意义吗?如果没有,为什么没有warning/error?如果有意义,对于一个对象的self.method意味着什么?
1.〉,为什么f7不能同时使用A的类和对象来调用?
1.〉,为什么f9不能同时使用A的类和对象来调用?
再讨论一下:
〈〉
class A
def self.f1
"f1"
end
def self.f2(&block)
(class << self; self; end).instance_eval do
define_method("f1", &block)
end
end
def self.f3(&block)
m=(class << self; self; end)
m.instance_eval do
define_method("f1", &block)
end
end
def self.f4(&block)
m=(class << self; self; end)
m.instance_eval do
def f1
"f4 is called"
end
end
end
def self.f5(&block)
m=(class << self; self; end)
m.instance_eval do
def f1
"f5 is called"
end
end
end
end
看来我现在离真相更近了,这里有最后一个需要让魔法显现出来的:
如果我做了
A.f2 do
"f2 is called"
end
A.f1
A.f3 do
"f3 is called"
end
A.f1
我可以用A.f2或A.f3调用覆盖f1方法,但是如果我直接在instance_eval块中定义方法,它不会达到相同的目标,这里有什么区别?
A.f4
A.f1
A.f5
A.f1
Aidof1仍然返回"f1"。我发现如果你使用def,那么方法就被定义并与特征类示例绑定,如果你使用define_method,那么方法就作为静态方法与类A绑定。
这里define_method和def的用法有什么区别?
1条答案
按热度按时间xlpyo6sf1#
您在这里提出的问题实际上是关于类、方法和对象在Ruby中如何工作的基础知识。
您所做的实际上只是
class
方法和instance
方法之间的区别。instance
方法在最基本的意义上意味着只能从示例化对象的级别调用该方法。这就是你在这里看到的语法。
在本例中,方法
hi
是类A
的一个示例方法,因此我们必须示例化一个对象来调用它。为了避免混淆大小写a和A,我将使用foo
而不是a
现在我们已经创建了
A
的instance
foo,因此我们可以在foo上调用方法hi
。接下来我们有
class
方法,或者可以在类的级别调用的方法,在Ruby中有多种语法可以实现这一点,以下所有语法在语义上都是等价的。上一个版本使用
class << self
的好处之一是我们可以在那一节定义多个方法,我根据我的工作在上面的最后两个方法之间来回切换,几乎从来没有使用过第一个版本,但这只是个人喜好。现在,到目前为止,我所说的几乎都是Ruby对标准OO类/方法定义的实现,类似的概念将在您使用过的任何其他OO语言C++、Java、C#等中找到。
最后一个让您感到困惑的地方是Ruby在哪里引入了元类的概念,或者它们在Ruby中通常被称为“特征类”。
这基本上意味着在类和示例之间存在一个你没有定义的类,这有点混乱;请阅读此处以了解更多信息(http://en.wikipedia.org/wiki/Metaclass)。
但这允许我们直接在示例上定义方法,这样方法就只存在于该示例上,而不存在于类的其他示例上。
这就是下面的语法的用武之地。
现在只为示例
foo
重写了方法hi
,这也可以用来定义只存在于示例中的全新方法。现在,如果我们示例化
A
的一个新示例方法
bar
在B上不存在;它只存在于示例foo
上。