正在阅读红宝石中使用的一些自我代码,仍然无法弄清楚一些例子:
class A
def hi
"hi"
end
def self.hello
"hello"
end
end
a=A.new
a.hi
A.hello
明白我可以使用下面的方法来改变实例方法def:
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] pry(main)&gt; A.f9
NoMethodError:未定义的方法f9' for A:Class
from (pry):40:in
pry &#39;
[21] pry(主要)&gt; a.f9
NoMethodError:未定义的方法f9' for #<A:0x007fb70717c0d0>
from (pry):41:in
pry &#39;
<<ERROR3>>
[22] pry(main)&gt;
[23] pry(主要)&gt; A.f7
NoMethodError:未定义的方法f7' for A:Class
from (pry):42:in
pry &#39;
[24] pry(主要)&gt; a.f7
NoMethodError:未定义的方法f7' for #<A:0x007fb70717c0d0>
from (pry):43:in
pry &#39;
[25] pry(主要)&gt; A.f9
NoMethodError:未定义的方法f9' for A:Class
from (pry):44:in
pry &#39;
[26] pry(主要)&gt; a.f9
NoMethodError:未定义的方法f9' for #<A:0x007fb70717c0d0>
from (pry):45:in
pry &#39;
您能否明确指出这些错误究竟是什么:请参阅&lt;&gt;标记
在对象中定义self.method是否有意义,如果没有,为什么没有warring /错误?如果它有意义,它对于一个物体的自我方法意味着什么?
&gt;,为什么f7不能同时使用A&C的类和对象调用?
&gt;,为什么f9不能使用A&C的类和对象调用?
再讨论一下:
&LT;&GT;
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块中直接使用def方法,它就不会实现相同的目标,那么差异是什么这里吗?
A.f4
A.f1
A.f5
A.f1
A.f1仍然返回&#34; f1&#34;。我发现如果你使用def,那么方法被定义并与特征类实例绑定,如果你使用define_method,那么该方法与类A绑定为静态方法。
define_method和def之间的区别是什么?
答案 0 :(得分:3)
您在这里提出的问题实际上是关于类,方法和对象如何在Ruby中工作的基础知识。
您所做的只是class
方法和instance
方法之间的区别。
instance
方法在最基本的意义上意味着只能从实例化对象的级别调用该方法。
这就是你在这里看到的语法。
class A
def hi
"hi"
end
end
在这种情况下,方法hi
是类A
的实例方法,因此我们必须实例化一个对象来调用它。为避免套管A与A之间出现混淆,我将使用foo
代替a
foo = A.new
foo.hi
现在我们刚刚创建了instance
foo A
,因此我们可以在foo上调用方法hi
。
接下来,我们有class
个方法,或者可以在类级别调用的方法。在Ruby中,有多种语法可以实现这一点,所有以下内容在语义上都是等效的。
class A
self.hello
"hello"
end
end
class A
A.hello
"hello"
end
end
class A
class << self
def hello
"hello"
end
end
end
现在使用class << self
的最后一个版本的一个好处是我们可以在该部分中定义多个方法。我在上面的最后两种方法之间来回移动,取决于我正在做什么,几乎从不使用第一个版本,但这只是个人偏好。
现在,到目前为止,我所说的一切都是Ruby的标准OO类/方法定义的实现,类似的概念将在你使用C ++,Java,C#等的任何其他OO语言中找到。 ..
你感到困惑的最后一篇文章是Ruby介入元类的想法,或者它们通常在Ruby中被称为“本征类”。
这基本上意味着在类和实例之间存在一个您没有定义的类。这有点令人困惑;请阅读此处以获得更清晰(http://en.wikipedia.org/wiki/Metaclass)。
但这允许我们做的是直接在实例上定义方法,因此方法仅存在于该实例上,而不存在于该类的其他实例上。
这是下面的语法所在。
class << foo
def hi
"hi from foo"
end
end
现在,仅为实例hi
覆盖了方法foo
。这也可以用于定义仅存在于实例上的全新方法。例如
class << foo
def bar
"bar"
end
end
现在,如果我们实例化A
b = A.new
b上不存在方法bar
;它只存在于实例foo
上。