' self'在ruby模块中

时间:2015-04-14 16:37:53

标签: ruby metaprogramming

module Cnblog2jekyll
  class << self
    attr_accessor :username


    [:archive_links, :article_links].each do |method_name|
      define_method method_name do
        instance_value = instance_variable_get(("@" + method_name.to_s).to_sym)
        instance_value ? instance_value : send("get_" + method_name.to_s)
        # @archive_links ? @archive_links : get_archive_links
      end
    end

    binding.pry

    def test
      binding.pry
    end


  end
end

请忽略大多数零件代码的含义并注意'binding.pry'的位置。

问题出现了:我在'binding.pry'的地方在pry控制台输入'self',它给出了这个结果:

From: /home/yanying/cnblog2jekyll/lib/cnblog2jekyll.rb @ line 20 :

    15:         instance_value = instance_variable_get(("@" + method_name.to_s).to_sym)
    16:         instance_value ? instance_value : send("get_" + method_name.to_s)
    17:         # @archive_links ? @archive_links : get_archive_links
    18:       end
    19:     end
 => 20:     binding.pry
    21: 
    22:     def test
    23:       binding.pry
    24:     end
    25: 

[1] pry(#<Class>)> self
=> #<Class:Cnblog2jekyll>
[2] pry(#<Class>)> self.class
=> Class
[3] pry(#<Class>)> self.ancestors
=> [#<Class:Cnblog2jekyll>, Module, Object, PP::ObjectMixin, Kernel, BasicObject]
[4] pry(#<Class>)> 
=> true
[2] pry(main)> Cnblog2jekyll.test

From: /home/yanying/cnblog2jekyll/lib/cnblog2jekyll.rb @ line 23 Cnblog2jekyll.test:

    22: def test
 => 23:   binding.pry
    24: end

[1] pry(Cnblog2jekyll)> self
=> Cnblog2jekyll
[2] pry(Cnblog2jekyll)> self.class
=> Module
[3] pry(Cnblog2jekyll)> self.ancestors
=> [Cnblog2jekyll]
[4] pry(Cnblog2jekyll)> 

所以,我的问题是:为什么'self'的第一个结果是'Class'?但第二个是“模块”?这里的魔力是什么?

2 个答案:

答案 0 :(得分:4)

由于您使用的是class << self,因此您打开了一个self单例类,其中的方法重新定义了当前self的方法,在您的情况下为{{1} }}

如果你有:

module Cnblog2jekyll

你打电话给class Cnblog2jekyll def foo end class << self def bar end end end 你得到一个Cnblog2jekyll.new.bar,因为bar被指定为类方法,而不是对象方法。在您的情况下,您的方法是undefined_method方法,因为module位于模块块内。

查看关于class << self习语的this question以及关于它的this article

答案 1 :(得分:1)

让我先回答你问题的第二部分。与其他语言相比,ruby中的类并不特别。

因此,类只是Ruby中所有其他类的对象。 Ruby中的所有类都是Class类的实例,包括Class类本身。现在,Module也是一个类,偶然是Class的父类。在Ruby中,你基本上有这个设置:

class BasicObject
  # The top-level base class. All objects in Ruby are an instance of BaseClass.
  # This class is effectively empty and is generally of little use on its own.
end

module Kernel
  # A module which is included about everywhere. It implements most of the basic
  # core methods of Ruby which you use every day including puts, raise and
  # require
end

class Object < BasicObject
  include Kernel

  # Almost all objects on ruby are instances of Object. Here, Ruby defines many
  # convenience methods available to about all objects, e.g., to_s, is_a? and
  # nil?
end

class Module < Object
  # A "special" class. All modules are an instance of this class. In fact, this:
  #
  #   module Foo
  #   end
  #
  # is mostly equivalent to
  #
  #   Foo = Module.new
end

class Class < Module
  # All classes are also modules. In fact, a class is basically a module which
  # can't be included or extended but can be instantiated.
  #
  # All objects in Ruby are instances of the Class class. This is where the
  # ring is closed. Because of this, you will see the ancestors chain the
  # way you got it from Pry.
end

你看,基础对象模型有点圆。这种结构是硬编码的,以便引导所谓的语言元模型。所有对象(包括类)都建立在这个基本结构上。

现在问题的第一部分:您在指定的类的上下文中调用pry,因此,self是您当前正在创建的类。请参阅Gabriel Lett的答案,了解其工作原理的详细信息。