class Object - delegate: Ruby Standard Library Documentation

# class Object

### Public Instance Methods

DelegateClass(superclass, &block) click to toggle source

The primary interface to this library. Use to setup delegation when defining your class.

    class MyClass < DelegateClass(ClassToDelegateTo) # Step 1
      def initialize
        super(obj_of_ClassToDelegateTo)              # Step 2
      end
    end

or:

    MyClass = DelegateClass(ClassToDelegateTo) do    # Step 1
      def initialize
        super(obj_of_ClassToDelegateTo)              # Step 2
      end
    end

Here’s a sample of use from Tempfile which is really a File object with a few special rules about storage location and when the File should be deleted. That makes for an almost textbook perfect example of how to use delegation.

    class Tempfile < DelegateClass(File)
      # constant and class member data initialization...

      def initialize(basename, tmpdir=Dir::tmpdir)
        # build up file path/name in var tmpname...

        @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600)

        # ...

        super(@tmpfile)

        # below this point, all methods of File are supported...
      end

      # ...
    end

Calls superclass method

    # File delegate.rb, line 394
    def DelegateClass(superclass, &block)
      klass = Class.new(Delegator)
      ignores = [*::Delegator.public_api, :to_s, :inspect, :=~, :!~, :===]
      protected_instance_methods = superclass.protected_instance_methods
      protected_instance_methods -= ignores
      public_instance_methods = superclass.public_instance_methods
      public_instance_methods -= ignores
      klass.module_eval do
        def __getobj__ # :nodoc:
          unless defined?(@delegate_dc_obj)
            return yield if block_given?
            __raise__ ::ArgumentError, "not delegated"
          end
          @delegate_dc_obj
        end
        def __setobj__(obj)  # :nodoc:
          __raise__ ::ArgumentError, "cannot delegate to self" if self.equal?(obj)
          @delegate_dc_obj = obj
        end
        protected_instance_methods.each do |method|
          define_method(method, Delegator.delegating_block(method))
          protected method
        end
        public_instance_methods.each do |method|
          define_method(method, Delegator.delegating_block(method))
        end
      end
      klass.define_singleton_method :public_instance_methods do |all=true|
        super(all) | superclass.public_instance_methods
      end
      klass.define_singleton_method :protected_instance_methods do |all=true|
        super(all) | superclass.protected_instance_methods
      end
      klass.define_singleton_method :instance_methods do |all=true|
        super(all) | superclass.instance_methods
      end
      klass.define_singleton_method :public_instance_method do |name|
        super(name)
      rescue NameError
        raise unless self.public_instance_methods.include?(name)
        superclass.public_instance_method(name)
      end
      klass.define_singleton_method :instance_method do |name|
        super(name)
      rescue NameError
        raise unless self.instance_methods.include?(name)
        superclass.instance_method(name)
      end
      klass.module_eval(&block) if block
      return klass
    end