module My_module
def self.module_func
puts 'self.module_func'
end
class << self
def what_func
puts 'what_func'
end
end
end
puts My_module.module_func
puts My_module.what_func
在 module 定义时,使用 class << sel f 的目的是什么呢?和 self.module_func 的区别又是什么
再问一个问题,这种在一个 module 中定义 method_missing 为什么必须也要使用 class<<self 呢? 在《ruby 元编程》书中也没见过这种技术
module Facter
....
class << self
# Allow users to call fact names directly on the Facter class,
# either retrieving the value or comparing it to an existing value.
def method_missing(name, *args)
question = false
if name.to_s =~ /\?$/
question = true
name = name.to_s.sub(/\?$/,'')
end
if fact = collection.fact(name)
if question
value = fact.value.downcase
args.each do |arg|
if arg.to_s.downcase == value
return true
end
end
# If we got this far, there was no match.
return false
else
return fact.value
end
else
# Else, fail like a normal missing method.
raise NoMethodError, "Could not find fact '%s'" % name
end
end
end
....
end
module M
N = 1
end
class C
include M
def self.foo
puts N
end
class << self
def bar
puts N
end
end
end
C.foo
C.bar
In a sense, the class keyword in Ruby is more like a scope operator than a class declaration. Yes, it does create classes that don’t yet exist, but you might argue that it does this as a side effect. For class, the core job is to move you in the context of the class, where you can define instance methods.
class << C; ancestors; end #====> [Module, Object, PP::ObjectMixin, Kernel, BasicObject]
C 的 singleton_class 的 ancestors 中并不包含 M 这个 module, 找不到 N,所以会报错。
class Demo
class << self
a = "aaaa"
define_method :puts_a do
puts a
end
def b
end
end
end
Demo.puts_a
module M
N = 1
end
class C
include M #常量定义在 M中
N = N #C::N=M::N
def self.foo
puts N
end
class << self
def bar
puts N #可以访问外层的常量C::N 了
end
end
end
C.foo #=>1
C.bar #=>1 ok
#------------------------------------------------
module M; N = 2; end #改变M::N, C中的C::N不变
C.foo #=> 1
C.bar #=> 1
class C
puts self
class << self
puts self
def bar
puts self
end
bar #在这里调用bar,会报错,找不到bar
end
bar
end
# 输出结果
C
#<Class:C>
C
从输出结果可以看到,class << self 这里,self 的作用域已经改变了,object_id 也变了,你可以自己输出来看看,参考 Class 类,当定义一个类的时候,an object of type Class is initialized and assigned to a global constant,可调用 constants 方法查看 self 包含的 constant。
这是 ruby 核心成员写的一篇文章 http://yugui.jp/articles/846
#30 楼 @zhenjunluo 和你说的 self 作用域什么的没有关系,定义方法的时候作用域和 self 也发生变化了,比如:
module M
N = 1
end
class C
include M
def bar # 这里改变了作用域,也改变了self
puts N
puts self
end
end
C.new.bar =>
1
#<C:0x8906a20>
http://ruby-china.org/topics/4777 这篇帖子可能对你有帮助。
class C
self.send(:include,M)
class << self
self.send(:include,M)
def bar
puts N
end
end
end
这个怎么样? C::N #1 Class::N #1 常量并不属于 C new 出来的对象
class Foo
class << self
a = "aaaa"
define_method :puts_a do
puts a
end
def b
end
end
end
Foo.puts_a #=> "aaaa"
class Bar
a = "aaaa"
class << self
define_method :puts_a do
puts a
end
def b
end
end
end
Bar.puts_a #=> error
同样都是类方法访问,但是结果却不一样,就是说class << self
这种用法创建了新的 scope(作用域),而别的写法就不一定;在 ruby 的元编程中,self
是一个非常重要的概念。
下面这篇基本是必须阅读的一篇 blog 了,作者就不用说了 http://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/
这是本坛里面的一个相关帖子,可以作辅助理解。 http://ruby-china.org/topics/1365