Ruby module 里面 class << self 的作用? 然后怎么扩展 class

flowerwrong · 2015年01月20日 · 最后由 flowerwrong 回复于 2015年01月20日 · 4028 次阅读

以下代码展示了如何从一个模块扩展一个类的实例方法 (include) 和类方法 (extend), 如何从一个模块扩展模块方法 (extend). 但遇到一个奇怪的问题,当在模块中使用 class << self 后该模块不能被其他类或者模块引用 (无论是include or extend) 详见module D, class S, class Y, 这是为什么?

module D
  class << self
    def say_hello_of_d
      puts 'D say hello'
    end
  end
end

module E
  def say_hello_of_e
    puts 'E say hello'
  end
end

module F
  extend E
end

module G
  include E
end

class H
  extend E
end

class S
  include E
end

class Y
  include D
end

D.say_hello_of_d # D say hello
# E.say_hello_of_e # undefined method `say_hello_of_e' for E:Module
F.say_hello_of_e # E say hello
# G.say_hello_of_e # undefined method `say_hello_of_e' for G:Module
H.say_hello_of_e # E say hello
S.new.say_hello_of_e # E say hello
# Y.new.say_hello_of_d #  undefined method `say_hello_of_d' for #<Y:0x000000013082b0>
Y.say_hello_of_d # undefined method `say_hello_of_d' for Y:Class

http://stackoverflow.com/questions/10039039/why-self-method-of-module-cannot-become-a-singleton-method-of-class https://www.ruby-forum.com/topic/4418176 http://blog.rubybestpractices.com/posts/gregory/041-issue-10.5-uses-for-modules.html http://www.techques.com/question/1-2353498/Is-extend-self-the-same-as-module_function? 👍 http://ruby-doc.com/docs/ProgrammingRuby/#Module.module_function

class << self 里写的方法是 模块/类 自身的方法。

#1 楼 @alixiaomiao 那我在模块中的class << self方法怎么扩展到类中呢?

class A
  def self.go
    puts 'hello a'
  end
end

class B < A
end

A.go # hello a
B.go # hello a

class << self ,就是打开 self 的单件类,可以在里面定义类方法

不符合 ruby mixin 的规范,所以不能这么做。

module D
  puts self.class    # 输出 Module
  class << self
    puts self.class   # 输出  Class
    def say_hello_of_d
      puts 'D say hello'
    end
  end
end

Module 的 singleton_class 就是 Class,不能 include 或 extend 到一个 class 中。 我能想到的就是用 delegate, 不过太难看了,不确定是否有问题。

require 'delegate'

module D  
  class << self
    def say_hello_of_d
      puts 'D say hello'
    end
  end
end

class Y < DelegateClass(D.singleton_class)
  def initialize
    super(D)
  end
end

y = Y.new
y.say_hello_of_d

#1 楼 @alixiaomiao #3 楼 @liangbin661831 #5 楼 @xzgyb #4 楼 @zgm 我希望我的 module fuction 既可以被其他类 includeextend , 自己也可以通过 ModuleName.funcName 调用。我如下做是因为,我要通过 ModuleName.funcName 调用

module D  
  class << self
    def say_hello_of_d
      puts 'D say hello'
    end
  end
end

D.say_hello_of_d

但是这样如果不做处理是不能被其他类 include 或者 extend 的。

如果只是想实现

我希望我的 module fuction 既可以被其他类 include 和 extend 自己也可以通过 ModuleName.funcName 调用

你可以这么做:

module D
  def say_hello_of_d
    puts "D say hello"
  end

  extend self
end

class C
  include D
  extend D
end

D.say_hello_of_d => "D say hello"
C.say_hello_of_d => "D say hello"
C.new.say_hello_of_d => "D say hello"
9 楼 已删除
需要 登录 后方可回复, 如果你还没有账号请 注册新账号