Ruby: 模块 extending/including 个模块
Ruby: modules extending/including modules
我正在努力更好地理解模块如何相互扩展和包含。
说我有模块 A:
module A
def learned_from_A
true
end
end
A.instance_methods # [:learned_from_A]
我把它的套路混成B:
module B
extend A
end
B.learned_from_A # true
我天真地试图给 C 一切 B 有:
module C
extend B
end
C.learned_from_A # NoMethodError
我想我已经解决了这个问题。当 B 扩展 A 时,A 的实例方法的副本通过 B 的单例 [=128] 绑定到 B =]:
B.singleton_methods # [:learned_from_A]
虽然 :learned_from_A 可在 B 上调用,但它不是 B[=86 之一=] 的 instance 方法,所以当 C 扩展 B, :learned_from_A 是 而不是 复制到 C.
如果 B 改为 included A,A 的实例方法的副本将会已包含在 B 自己的实例方法中。
module B
include A
end
B.instance_methods # [:learned_from_A]
然后,C可以扩展B,以及B的所有实例方法(包括:learned_from_A) 将被复制并绑定到 C.
module C
extend B
end
C.singleton_methods # [:learned_from_A]
使 :learned_from_A 在 B 和 C, B 可以扩展 and 包括 A.
module B
include A
extend A
end
B.instance_methods # [:learned_from_A]
B.singleton_methods # [:learned_from_A]
module C
extend B
end
C.instance_methods # []
C.singleton_methods # [:learned_from_A]
更现实一点,如果我希望 A 的方法可以在 B 上调用,并且 B定义自己的另一种方法,和可以把整个曲目混成C,我不能这样做:
module B
extend A
include A
def self.buzz
true
end
end
module C
extend B
end
B只能共享它的实例方法,不能共享它的单例方法。因此,要使方法既可在 B 上调用又可共享给其他对象,必须将其定义为实例方法并扩展到 B 本身:
module B
extend A
include A
extend self
def buzz
true
end
end
module C
extend B
end
将所有这些放在一起进行了大量的试验和错误。这是查看正在发生的事情的准确方法吗?
I mix its bag of tricks into B
这句话和你的问题总的来说让我相信在 include
/extend
的概念上存在一些误解。我提前道歉,因为我没有完全理解这个问题。
例如你有这样的模块:
module A
def a
puts "a"
end
def self.b
puts "b"
end
end
如您所见,有两种类型的方法:
- singleton_methods
- instance_methods
这是证明它们实际上不同的最简单方法:
A.singleton_methods
=> [:b]
A.instance_methods
=> [:a]
A.a
NoMethodError: undefined method `a' for A:Module
A.b
b
=> nil
如果您简单地include A
,您就是将其instance 方法添加到当前模块instance 方法。当您简单地执行 extend A
时,您将其 instance 方法添加到当前模块 singleton 方法中。
module B
include A
end
module C
extend A
end
B.instance_methods
=> [:a]
B.singleton_methods
=> []
C.instance_methods
=> []
C.singleton_methods
=> [:a]
还有一点要说的是,您可以 extend self
但不能 include self
,因为这没有任何意义,而且还会引发异常。
module D
extend self
def a
puts "a"
end
def self.b
puts "b"
end
end
D.singleton_methods
=> [:b, :a]
D.instance_methods
=> [:a]
D.a
a #no error there because we have such singleton method
=> nil
我想这些东西可以帮助你。 Whosebug 上有很多关于 extend
/include
的问题,您可以查看 (example).
以下似乎至少适用于 A
到 B
到 C
module A
def learned_from_A
true
end
end
module B
prepend A
end
B.learned_from_A # true
module C
extend B
end
C.learned_from_A # true
我正在努力更好地理解模块如何相互扩展和包含。
说我有模块 A:
module A
def learned_from_A
true
end
end
A.instance_methods # [:learned_from_A]
我把它的套路混成B:
module B
extend A
end
B.learned_from_A # true
我天真地试图给 C 一切 B 有:
module C
extend B
end
C.learned_from_A # NoMethodError
我想我已经解决了这个问题。当 B 扩展 A 时,A 的实例方法的副本通过 B 的单例 [=128] 绑定到 B =]:
B.singleton_methods # [:learned_from_A]
虽然 :learned_from_A 可在 B 上调用,但它不是 B[=86 之一=] 的 instance 方法,所以当 C 扩展 B, :learned_from_A 是 而不是 复制到 C.
如果 B 改为 included A,A 的实例方法的副本将会已包含在 B 自己的实例方法中。
module B
include A
end
B.instance_methods # [:learned_from_A]
然后,C可以扩展B,以及B的所有实例方法(包括:learned_from_A) 将被复制并绑定到 C.
module C
extend B
end
C.singleton_methods # [:learned_from_A]
使 :learned_from_A 在 B 和 C, B 可以扩展 and 包括 A.
module B
include A
extend A
end
B.instance_methods # [:learned_from_A]
B.singleton_methods # [:learned_from_A]
module C
extend B
end
C.instance_methods # []
C.singleton_methods # [:learned_from_A]
更现实一点,如果我希望 A 的方法可以在 B 上调用,并且 B定义自己的另一种方法,和可以把整个曲目混成C,我不能这样做:
module B
extend A
include A
def self.buzz
true
end
end
module C
extend B
end
B只能共享它的实例方法,不能共享它的单例方法。因此,要使方法既可在 B 上调用又可共享给其他对象,必须将其定义为实例方法并扩展到 B 本身:
module B
extend A
include A
extend self
def buzz
true
end
end
module C
extend B
end
将所有这些放在一起进行了大量的试验和错误。这是查看正在发生的事情的准确方法吗?
I mix its bag of tricks into B
这句话和你的问题总的来说让我相信在 include
/extend
的概念上存在一些误解。我提前道歉,因为我没有完全理解这个问题。
例如你有这样的模块:
module A
def a
puts "a"
end
def self.b
puts "b"
end
end
如您所见,有两种类型的方法:
- singleton_methods
- instance_methods
这是证明它们实际上不同的最简单方法:
A.singleton_methods
=> [:b]
A.instance_methods
=> [:a]
A.a
NoMethodError: undefined method `a' for A:Module
A.b
b
=> nil
如果您简单地include A
,您就是将其instance 方法添加到当前模块instance 方法。当您简单地执行 extend A
时,您将其 instance 方法添加到当前模块 singleton 方法中。
module B
include A
end
module C
extend A
end
B.instance_methods
=> [:a]
B.singleton_methods
=> []
C.instance_methods
=> []
C.singleton_methods
=> [:a]
还有一点要说的是,您可以 extend self
但不能 include self
,因为这没有任何意义,而且还会引发异常。
module D
extend self
def a
puts "a"
end
def self.b
puts "b"
end
end
D.singleton_methods
=> [:b, :a]
D.instance_methods
=> [:a]
D.a
a #no error there because we have such singleton method
=> nil
我想这些东西可以帮助你。 Whosebug 上有很多关于 extend
/include
的问题,您可以查看 (example).
以下似乎至少适用于 A
到 B
到 C
module A
def learned_from_A
true
end
end
module B
prepend A
end
B.learned_from_A # true
module C
extend B
end
C.learned_from_A # true