Singleton method vs. class method

后端 未结 5 909
一向
一向 2021-02-08 16:31

Are class method and singleton method doing the same or different? Here is an example.

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


        
5条回答
  •  旧时难觅i
    2021-02-08 16:57

    Since all methods are implemented and stored by the class definition, it should be impossible for an object to define its own methods. However, Ruby provides a way around this - you can define methods that are available only for a specific object. Such methods are called Singleton Methods.

    class Instance
      def instance_method
        puts "instance method called"
      end
    end
    
    in_obj = Instance.new
    

    The above statement you a reference object of class Instance, you might get a different id.

    #
    

    let's call the instance method with the object and we will get output.

    in_obj.instance_method
    instance method called
    

    Now, create the singleton method.

    sin_obj = Instance.new
    #
    def sin_obj.singleton_method
      puts "singleton method called"
    end
    

    calling the singleton method

    sin_obj.sigleton_method
    singleton method called
    

    Here, the object sin_obj has the singleton method singleton_method. This is a singleton method because it belongs to just one instance of a class and will not be shared with others.

    However, singleton methods contradict that instance objects cannot hold methods, only class definitions (objects of class Class) can. It happens that the truth is somewhere in-between. When you declare a singleton method on an object, Ruby automatically creates a class to hold just that method. This class is called the 'metaclass' of the object. All subsequent singleton methods of this object goes to its metaclass. Whenever you send a message to the object, it first looks to see whether the method exists in its metaclass. If it is not there, it gets propagated to the actual class of the object and if it is not found there, the message traverses the inheritance hierarchy. Let defined the class method in the same Instance class. Now, lets check the fact that I stats above with an example.

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

    Verify the fact that signleton method definition goes to the meta class.

    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
     #>
    

    Let look how meta class is implemented.

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

    The class << self syntax changes the current self to point to the metaclass of the current object. Since we are already inside an instance method, this would be the instance's metaclass. The method simply returns self which at this point is the metaclass of the instance.

    A metaclass is almost a class in many respects. It however can't be instantiated. To check this see the example below.

    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*
    

    In Ruby, both 'metaclass' and 'singleton class' means the same. You'll find them being used interchangeably in Ruby literature.

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

    However, one can also follow this syntax to defined a class method

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

    calling class_method

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

    It consists of building a new anonymous class only for the current object (self). To create the anonymous class, we use the << notation. Look closely how class method and singleton method are defined you find the difference. consider the example.

    class Instance 
     puts self
     def meth
      p self
     end
    end
    

    here, outside of meth method self is nothing but the class, inside an instance_method the self pointing to the current instance or object.

    Additionally, You can also check that a method responds to a particular object or not.

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

提交回复
热议问题