gpt4 book ai didi

ruby元编程和关键字自混淆

转载 作者:太空宇宙 更新时间:2023-11-03 18:14:14 25 4
gpt4 key购买 nike

正在阅读ruby中使用的一些self代码,仍然无法弄清楚一些例子:

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)> A.f9NoMethodError:未定义的方法 f9' for A:Class
from (pry):40:in
pry '[21] pry (主要)> a.f9NoMethodError:未定义的方法 f9' for #<A:0x007fb70717c0d0>
from (pry):41:in
pry '

<<ERROR3>> 

[22] pry (主要)>[23] pry (主)> A.f7NoMethodError:未定义的方法 f7' for A:Class
from (pry):42:in
pry '[24] pry (主要)> a.f7NoMethodError:未定义的方法 f7' for #<A:0x007fb70717c0d0>
from (pry):43:in
pry '[25] pry (主)> A.f9NoMethodError:未定义的方法 f9' for A:Class
from (pry):44:in
pry '[26] pry (主要)> a.f9NoMethodError:未定义的方法 f9' for #<A:0x007fb70717c0d0>
from (pry):45:in
pry '

你能帮忙指出这些错误到底是什么吗:引用<>标记

  1. 看到 <>,我的问题:

在对象中定义 self.method 是否有意义,如果没有,为什么没有警告/错误?如果它有意义,它对对象的 self.method 意味着什么?

  1. >,为什么不能同时使用 A 的类和对象调用 f7?

  2. >,为什么不能同时使用 A 的类和对象调用 f9?

更多讨论:

<>

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 block 中定义方法,它不会实现相同的目标,这里有什么区别?

A.f4

A.f1

A.f5

A.f1

A.f1 仍然返回“f1”。我发现,如果你使用 def,那么该方法被定义并与 eigen 类实例绑定(bind),如果你使用 define_method,则该方法作为静态方法与类 A 绑定(bind)。

这里 define_method 和 def 的用法有什么区别?

最佳答案

您在这里提出的问题实际上是关于类、方法和对象在 Ruby 中如何工作的基础知识。

你所做的只是class之间的区别方法和 instance方法。

instance方法在最基本的意义上意味着只能从实例化对象的级别调用该方法。

这就是您在此处看到的语法。

class A
def hi
"hi"
end
end

在这种情况下,方法 hi是类 A 的实例方法所以我们必须实例化一个对象来调用它。为了避免在大小写 a 和 A 之间混淆,我将使用 foo而不是 a

foo = A.new
foo.hi

现在我们刚刚创建了一个 instanceA因此我们可以调用方法 hi在 foo 上。

接下来我们有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

方法bar b 上不存在;它只存在于实例 foo 上.

关于ruby元编程和关键字自混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28782579/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com