【问题标题】:Ruby Singleton methods for class and objects用于类和对象的 Ruby Singleton 方法
【发布时间】:2011-07-20 09:31:40
【问题描述】:

我正在学习 Ruby 单例,我找到了一些方法来定义和获取类和对象单例方法的列表。

类单例方法

类单例方法的定义方式:

class MyClass

  def MyClass.first_sing_method
    'first'
  end

  def self.second_sing_method
    'second'
  end

  class << self
    def third_sing_method
      'third'
    end
  end

  class << MyClass
    def fourth_sing_method
      'fourth'
    end
  end
end

def MyClass.fifth_sing_method
  'fifth'
end

MyClass.define_singleton_method(:sixth_sing_method) do
  'sixth'
end

获取类单例方法列表的方法:

#get singleton methods list for class and it's ancestors 
MyClass.singleton_methods

#get singleton methods list for current class only  
MyClass.methods(false)

对象单例方法

对象单例方法的定义方式

class MyClass
end

obj = MyClass.new

class << obj
  def first_sing_method
    'first'
  end
end

def obj.second_sing_method
  'second'
end

obj.define_singleton_method(:third_sing_method) do
  'third'
end

获取对象单例方法列表的方法

#get singleton methods list for object and it's ancestors  
obj.singleton_methods

#get singleton methods list for current object only
obj.methods(false)

还有其他方法可以做到这一点吗?

【问题讨论】:

  • 尽管这个问题很久以前就已经回答过了,为了完整起见:您也可以使用方法 class_eval 和 instance_eval。例如:obj.instance_eval {def hi;puts "hi";end} 或 Object.class_eval {def self.foo;puts "foo";end}(这与通过开放类扩展相同),或last: Object.instance_eval{def bar;puts "bar";end} (这样就打开了Object的虚类,虽然self和前面一样,但还是在不同的环境中!)
  • 不错的总结,应该是个wiki

标签: ruby


【解决方案1】:

首先,列出单例方法的方法是使用singleton_methodsmethods 方法返回对象的公共和受保护方法的名称列表。此外,它在Object 类中定义。尝试extending 一个实例。这是最优雅的方式之一,因为它支持代码重用并且在我看来非常面向对象:

class Foo
  def bar
    puts "Hi"
  end
end

module Bar
  def foo
    puts "Bye"
  end
end

f = Foo.new
f.bar
#=> hi

f.extend Bar
f.foo
#=> bye

f.methods(false)
#=> []
# the module we extended from is not a superclass
# therefore, this must be empty, as expected

f.singleton_methods
#=> ["foo"]
# this lists the singleton method correctly

g = Foo.new
g.foo
#=> NoMethodError

编辑:在评论中你问为什么methods(false) 在这种情况下什么都不返回。通读 C 代码后,似乎:

  • methods 返回对象可用的所有方法(包括模块中的方法)
  • singleton_methods 返回对象的所有单例方法(包括模块中的方法)(documentation)
  • singleton_methods(false) 返回对象的所有单例方法,但那些在包含的模块中声明的方法
  • methods(false) 应该通过调用 singleton_methods 返回单例方法,它也将参数 false 传递给它;这是错误还是功能 - 我不知道

希望这能稍微澄清一下这个问题。底线:致电singleton_methods,似乎更可靠。

【讨论】:

  • 谢谢,不错的功能,我不知道。但是为什么methods(false) 不显示添加的方法?
  • 我也可以这样扩展class
  • 我对@9​​87654338@进行了实验,得出的结论是method(false)只显示自己对象的方法,它不显示祖先链中上层类的方法
  • 在之前删除的评论中,您说methods()instance_methods() 的别名,是真的吗?在这种情况下,instance_methods() 如何返回单例方法?单例和实例方法是不同的。
  • 抱歉有很多问题,但我试着理解
【解决方案2】:

更多方法:

类单例方法

class << MyClass
  define_method :sixth_sing_method do
    puts "sixth"
  end
end

class MyClass
  class << self
    define_method :fourth_sing_method do
      puts "seventh"
    end
  end
end

对象单例方法

class << obj
  define_method :fourth_sing_method do
    puts "fourth"
  end
end

接下来,您可以将define_methoddefine_singleton_methodsend 结合使用,例如

obj.send :define_singleton_method, :nth_sing_method, lambda{ puts "nth" }

及其所有可能的组合。要使用define_method,您需要首先捕获单例类(同样适用于类对象)

singleton_class = class << obj; self end
singleton_class.send :define_method, :nth_sing_method, lambda{ puts "nth" }

另一种方法是在单例类对象上使用class_eval

singleton_class.class_eval do
  def nth_sing_method
    puts "nth"
  end
end

然后你可以再次将sendclass_eval 结合起来......

我猜有无数种方法:)

【讨论】:

    【解决方案3】:

    对象单例方法

    instance_eval

    class A
    end
    
    a = A.new
    
    a.instance_eval do
    def v 
    "asd"
    end
    end
    
     a.singleton_methods
     => [:z, :v] 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-28
      • 1970-01-01
      • 1970-01-01
      • 2011-10-23
      • 1970-01-01
      • 2014-12-30
      • 2023-03-22
      • 1970-01-01
      相关资源
      最近更新 更多