Implementing Class and Singleton Methods

Problem

You want to associate a new method with a class (as opposed to the instances of that class), or with a particular object (as opposed to other instances of the same class).

Solution

To define a class method, prefix the method name with the class name in the method definition. You can do this inside or outside of the class definition.

The Regexp.is_valid? method, defined below, checks whether a string can be compiled into a regular expression. It doesn't make sense to call it on an already instantiated Regexp, but it's clearly related functionality, so it belongs in the Regexp class (assuming you don't mind adding a method to a core Ruby class).

class Regexp def Regexp.is_valid?(str) begin compile(str) valid = true rescue RegexpError valid = false end end end Regexp.is_valid? "The horror!" # => true Regexp.is_valid? "The)horror!" # => false

Here's a Fixnum.random method that generates a random number in a specified range:

def Fixnum.random(min, max) raise ArgumentError, "min > max" if min > max return min + rand(max-min+1) end Fixnum.random(10, 20) # => 13 Fixnum.random(-5, 0) # => -5 Fixnum.random(10, 10) # => 10 Fixnum.random(20, 10) # ArgumentError: min > max

To define a method on one particular other object, prefix the method name with the variable name when you define the method:

company_name = 'Homegrown Software' def company_name.legalese return "#{self} is a registered trademark of ConglomCo International." end company_name.legalese # => "Homegrown Software is a registered trademark of ConglomCo International." 'Some Other Company'.legalese # NoMethodError: undefined method 'legalese' for "Some Other Company":String

 

Discussion

In Ruby, a singleton method is a method defined on one specific object, and not available to other instances of the same class. This is kind of analagous to the Singleton pattern, in which all access to a certain class goes through a single instance, but the name is more confusing than helpful.

Class methods are actually a special case of singleton methods. The object on which you define a new method is the Class object itself.

Some common types of class methods are listed here, along with illustrative examples taken from Ruby's standard library:

When you define a singleton method on an object other than a class, it's usually to redefine an existing method for a particular object, rather than to define a brand new method. This behavior is common in frameworks, such as GUIs, where each individual object has customized behavior. Singleton method definition is a cheap substitute for subclassing when you only need to customize the behavior of a single object:

class Button #A stub method to be overridden by subclasses or individual Button objects def pushed end end button_a = Button.new def button_a.pushed puts "You pushed me! I'm offended!" end button_b = Button.new def button_b.pushed puts "You pushed me; that's okay." end Button.new.pushed # button_a.pushed # You pushed me! I'm offended! button_b.pushed # You pushed me; that's okay.

When you define a method on a particular object, Ruby acts behind the scenes to transform the object into an anonymous subclass of its former class. This new class is the one that actually defines the new method or overrides the methods of its superclass.

Категории