方法只针对一个实例?他们在Ruby中称之为什么?

时间:2013-11-03 15:50:36

标签: ruby singleton

我知道有“实例方法”,“类方法”,但这些类型的方法被称为,例如:

s1 = "This is my STRING!"

def s1.m1
  downcase
end

p s1     # => "This is my STRING!"
p s1.m1   # => "this is my string!"

在“string”类的s1“instance”上调用“m1”方法是什么类型的方法?这真的很奇怪,因为如果我尝试的话,我根本不知道这是可能的:

s2 = "This is ANOTHER string"
s2.m1 # => Won't work!

哪种有意义,但不确定为什么在类的实例上定义像m1这样的方法是有用的。

4 个答案:

答案 0 :(得分:4)

它们被称为单例方法,可以定义如下:

class Person
  def favorite_meal
    "Big Mac"
  end
end

Fred, Joe = 2.times.map { Person.new }

def Fred.favorite_meal
  "Le Big Mac"
end

Joe.favorite_meal #=> Big Mac
Fred.favorite_meal #=> Le Big Mac

定义相同单例方法的其他方法是:

Fred.define_singleton_method :favorite_meal do "Le Big Mac" end

class << Fred
  def favorite_meal
    "Le Big Mac"
  end
end

愿力量与你同在。


更新:回答评论中的2个问题。

让我从第二个开始。无论您使用常量还是变量,都取决于您。写fred = Person.new是完全可以的。但是:

  1. 具有不同属性的对象通常需要正确的名称,这些名称是正确的资格。

  2. 我写了一个有用的宝石y_support/name_magic,通过分配常量来工作。

  3. gem install y_support安装,然后尝试:

    require 'y_support/name_magic'
    
    class Dog
      include NameMagic
      def speak; puts "Bow wow!" end
    end
    
    Spot, Rover = 2.times.map { Dog.new }
    

    现在Dog类知道它的实例,实例知道它们的名字。

    Dog.instances.map { |dog| dog.name } #=> :Spot, :Rover
    Dog.instances.names # the simpler way to say the same
    

    这在这个特定的例子中没用(并且在其他地方非常有用),但无论如何,它给了我一个习惯,就是给对象提供个性化的专有名称。

    至于第一个问题,def Fred.foobar是最基本的一次性单身方法定义。如果要在单例类中定义几个单例方法或别名或包含模块,请使用class << Fred

    module Foo
      def bar; "Fretbar!" end
    end
    
    class << Fred
      include Foo
      alias le_favorite favorite_meal
    end
    
    Fred.bar #=> Fretbar!
    Fred.le_favorite #=> "Le Big Mac"
    

    使用Fred.define_singleton_method语法可以实现最高级的功能,并且使用第4种方法,我之前没有提到过:

    local_var = 42
    
    Fred.singleton_class.class_exec do
      define_method :baz do local_var + 1 end
    end
    
    Fred.baz #=> 43
    

    这种方法使用闭包,它保留与变量local_var的绑定。试一试

    local_var = 32
    Fred.baz #=> 33
    

    所以这是关于闭包语法的特殊之处,它通常是一个神奇的解决令人讨厌的编程问题。

答案 1 :(得分:2)

它们被称为对象Singleton Methods

A example我可以想到你可以在哪里使用它:

您有一个特殊的日志记录类,您必须将日志记录限制为仅一个实例,因为您希望您的日志记录文件干净整洁。

也许不是最好的例子,但如果您对用例感兴趣,请查找Singleton Pattern的用例,您应该在那里找到答案。

答案 2 :(得分:1)

他们被称为单身方法。以下是检查这些内容的方法:

s1 = "This is my STRING!"

def s1.m1
  downcase
end

klass= s1.singleton_class # => #<Class:#<String:0x902d4e8>>
klass.instance_methods(false) # => [:m1]
s1.method(:m1).owner # => #<Class:#<String:0x902d4e8>>
s1.singleton_methods # => [:m1]
  

但不确定为什么在类的实例上定义像m1这样的方法是有用的。

这些单例方法(m1)只能由s1调用,因为您在s1的单例类中定义它。但不是String类的任何其他实例。当你有一些对象独有的行为时,无论是否属于同一个类或不同的类,都需要这些行为。

  

s2.m1#=&gt;不会工作!

因为你没有在s1的单例类中定义它。

答案 3 :(得分:0)

“(...)但不确定为什么在类的实例上定义像m1这样的方法是有用的。”

这使得这种行为成为可能:

class Test
  def self.some_meth
  end
end

Test只是Class的一个实例,some_method被添加到这个特定的实例中。

p Test.singleton_methods #=> [:some_meth]