单身方法与类方法

时间:2015-12-23 06:13:51

标签: ruby singleton

类方法和单例方法是相同还是不同?这是一个例子。

class C
  def self.classmethod
    puts "class method #{self}"
  end
end

C.classmethod  # class method C
c = C.new

def c.singletonmethod
  puts "instance method #{self}"
end

c.singletonmethod  # instance method #<C:0x0000000118ed08>

5 个答案:

答案 0 :(得分:17)

Ruby中发生的大多数事情涉及包含的类和模块 实例方法的定义

class C
  def talk
    puts "Hi!"
  end
end

c = C.new
c.talk
Output: Hi!

但正如您之前看到的(甚至比您在类中看到实例方法更早),您还可以直接在单个对象上定义单例方法:

obj = Object.new
def obj.talk
  puts "Hi!"
end
obj.talk
#377
#Output: Hi!

在给定对象上定义单例方法时,只有该对象可以调用该方法。正如您所见,最常见的单例方法类型是类方法 - 一种基于个体添加到Class对象的方法:

class Car
  def self.makes
    %w{ Honda Ford Toyota Chevrolet Volvo }
  end
end

但是任何对象都可以添加单例方法。基于每个对象定义方法驱动行为的能力是Ruby设计的标志之一。

单身人士课程

Singleton类是匿名的:虽然它们是类对象(类Class的实例),但它们会自动弹出而不会给出名称。尽管如此,您可以打开单例类的类定义主体,并向其添加实例方法,类方法和常量,就像使用常规类一样。

注意:

<强> Every object has two classes:

■它是一个实例的类

■其单身类

----------------------------------------------- -----------------

最后我强烈建议你观看。

1:The Ruby Object Model and Metaprogramming有关 singleton method vs. class method ruby

的详细信息

2:MetaProgramming - Extending Ruby for Fun and Profit - Dave Thomas

希望这能帮到你!!!

答案 1 :(得分:16)

没有区别。 Ruby中没有类方法。如果对象恰好是mutateAndGetPayload: ({clientMutationId, ...args}) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve("Resolved") }, 500) }) }, ... 类的实例,“类方法”只是我们人类调用单例方法的名称。

答案 2 :(得分:6)

在ruby类中也是一个对象。因此,在您的示例中,classmethod是对象C的单例方法,而singletonmethod是对象c的单例方法。

我强烈推荐Paolo Perrotta的书“Metaprogramming Ruby”。

答案 3 :(得分:3)

  

由于所有方法都是由类定义实现和存储的,因此对象不可能定义自己的方法。但是,Ruby提供了一种方法 - 您可以定义仅适用于特定对象的方法。这种方法称为Singleton方法。

class Instance
  def instance_method
    puts "instance method called"
  end
end

in_obj = Instance.new

上面的语句你是Instance类的引用对象,你可能得到一个不同的id。

#<Instance:0x00000000e9ee68>

让我们用对象调用实例方法,我们将得到输出。

in_obj.instance_method
instance method called

现在,创建单例方法。

sin_obj = Instance.new
#<Instance:0x00000000e98d60>
def sin_obj.singleton_method
  puts "singleton method called"
end

调用单例方法

sin_obj.sigleton_method
singleton method called
  

这里,对象sin_obj具有单例方法singleton_method。这是一个   单例方法因为它只属于一个类的一个实例   并且不会与他人分享。

     

但是,单例方法与实例对象不相矛盾   hold方法,只有类定义(Class类的对象)才可以。它   碰巧说实话介于两者之间。   当您在对象上声明单例方法时,Ruby会自动创建一个类来保存该方法。该类称为对象的“元类”。此对象的所有后续单例方法都转到其元类。每当您向对象发送消息时,它首先会查看该方法是否存在于其元类中。如果它不存在,它将传播到对象的实际类,如果在那里找不到,则消息遍历继承层次结构。   我们在同一个Instance类中定义类方法。   现在,让我们通过一个例子检查上面我的统计数据。

foo = "Hey I am a string"
def foo.foo_instance_method
    p self.upcase
end

验证signleton方法定义转到元类的事实。

p foo.class.instance_methods.include?:foo_instance_method
 false
p foo.metaclass.instance_methods.include?:foo_instance_method
 true
p foo.metaclass.class
 Class
p foo.metaclass
 #<Class:#<String:0x00000000e8f0f8>>

让我们看看如何实现元类。

class Instance
  def metaclass
    class << self
      self
    end
  end
end

班级&lt;&lt; self语法将当前self更改为指向当前对象的元类。由于我们已经在实例方法中,因此这将是实例的元类。该方法只返回self,此时是实例的元类。

  

元类在很多方面几乎都是一个类。但它不可能   实例化。要查看此内容,请参阅下面的示例。

a = Instance.new
a.metaclass.new
You will get is error when try to intantiate the meta class.
*TypeError: can't create instance of singleton class*
  

在Ruby中,'metaclass'和'singleton class'都意味着相同。你会   发现它们在Ruby文献中可以互换使用。

class Instance
    def self.class_method #instead one can use def Instance.class_method
        puts "class method called"        
    end
end

但是,也可以按照此语法定义类方法

class Instance
  class << self
    def show
      puts "Class method show invoked"
    end
  end
end

调用class_method

Instance.class_method
class method called
Instance.show 
Class method show invoked

它包括仅为当前对象(self)构建一个新的匿名类。要创建匿名类,我们使用&lt;&lt;符号。仔细查看如何定义类方法和单例方法,找到差异。 考虑这个例子。

class Instance 
 puts self
 def meth
  p self
 end
end

这里,在方法之外,self只是类,在instance_method中指向当前实例或对象的self。

此外,您还可以检查方法是否响应特定对象。

p Instance.new.respond_to?(:singleton_method)
p Instance.new.respond_to?(:class_method)

答案 4 :(得分:0)

他们是相对的观念;透视问题。从A类的单例类的角度来看,它的实例方法是从A(A实例)的角度来看的类方法。