Final/closed classes in Ruby (was: Sharp knives and glue)

The 'Sharp knives and glue' thread inspired this. It's probably been
done before but here's my implementation of a final and/or closed class:

# Make a class unsubclassable
class Class
   def final(klass)
      class << klass
         def inherited(subclass)
            error = "Illegal attempt to subclass #{self} with
#{subclass}"
            raise RuntimeError, error
         end
      end
   end
end

class Foo
   final(self) # No subclasses allowed
end

# Boom!
class Bar < Foo
end

# Close a class (no method definitions or redefinitions)

class Module
   def close(klass)
      class << self
         def method_added(method)
            error = "cannot add or change method #{method} to closed"
            error += " class #{self}"
            raise RuntimeError, error
         end
      end
   end
end

class Foo
   def test
      puts "hello"
   end
   close(self) # No method additions/redefinitions allowed
end

# Boom!
class Foo
   def test2
      puts "eh?"
   end
end

This could probably be combined into a single method, and perhaps put in
the Kernel module as well.

Anyway, there you have it.

Regards,

Dan

This communication is the property of Qwest and may contain confidential or
privileged information. Unauthorized use of this communication is strictly
prohibited and may be unlawful. If you have received this communication
in error, please immediately notify the sender by reply e-mail and destroy
all copies of the communication and any attachments.

} The 'Sharp knives and glue' thread inspired this. It's probably been
} done before but here's my implementation of a final and/or closed class:
}
} # Make a class unsubclassable
[...]
} # Close a class (no method definitions or redefinitions)
[...]
} class Foo
} def test
} puts "hello"
} end
} close(self) # No method additions/redefinitions allowed
} end
[...]

class Foo
  def test
    puts "hello"
  end
  freeze #this already exists and does what you want
end

} Regards,
} Dan
--Greg

···

On Fri, May 12, 2006 at 06:27:13AM +0900, Berger, Daniel wrote:

Has potential, but why not just do:

class Class
   def final # or even final!
     class << self
       def inherited(subclass)
         error = "Illegal attempt to subclass #{self} with
#{subclass}"
         raise RuntimeError, error
       end
     end
   end
end

class Foo
   final
end

class Bar < Foo
end

RuntimeError: Illegal attempt to subclass Foo with
Bar
         from (irb):7:in `inherited'
         from (irb):17

Unfortunately, it raises an exception way too late.

try:

class Foo
   final
end

begin
class Bar < Foo
end
# Foo.inherited(Bar) pretty much happens here
rescue
end

b = Bar.new

···

On May 11, 2006, at 5:27 PM, Berger, Daniel wrote:

The 'Sharp knives and glue' thread inspired this. It's probably been
done before but here's my implementation of a final and/or closed class:

# Make a class unsubclassable
class Class
   def final(klass)
      class << klass
         def inherited(subclass)
            error = "Illegal attempt to subclass #{self} with
#{subclass}"
            raise RuntimeError, error
         end
      end
   end
end

class Foo
   final(self) # No subclasses allowed
end

# Boom!
class Bar < Foo
end