# Using closures as a replacement for "class", @, and @@

**URL:** <https://www.ruby-forum.com/t/using-closures-as-a-replacement-for-class-and/107723>\
**Category:** Ruby\
**Created:** [June 25, 2007, 6:36pm UTC](https://www.ruby-forum.com/t/using-closures-as-a-replacement-for-class-and/107723 "2007-06-25T18:36:10Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![snowbird122](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c68b51/32.png) [@snowbird122](https://www.ruby-forum.com/u/snowbird122)\
**Post date:** [June 25, 2007, 6:36pm UTC](https://www.ruby-forum.com/t/using-closures-as-a-replacement-for-class-and/107723/1 "2007-06-25T18:36:10Z")

</div>

Some of you might find it interesting that ruby’s closures/blocks can  
be used as an alternative for defining classes/objects. It’s actually  
quite simple. You just do this:

- instead of class/def initialize, you use a function/method to define  
how to create/initialize an object of that “class” (the function  
name).
- add methods by calling define\_method w/ a block on the metaclass on  
the object that the “class” function will return.
- local variables of the “class” function become “instance” variables  
since all of the blocks used for defining methods are closures and  
have access to them.
- a variable outside that “class” function that is accessible can be  
used a “class variable”.
- inheritance is easily done by starting with an object of the base  
class
- multiple inheritance is probably best done with using a “has-a”  
relationship and delegating particular methods to particular member  
objects. You could also mixin using Object#extend.
- calling a base class method can be done several ways: a) renaming  
the base method before redefining the derived method, b) store the  
base method in an instance variable, c) use a “has-a” relationship and  
store the base object in an instance variable - inherit/delegate or  
define each method explicitly.

All this is mostly academic. You should be able to base a complete  
object-oriented language on closures.

There are a few advantages:

- don’t need keywords for classes: class, module, self, super, etc.
- don’t need to prefix instance/class variable with @ and @@. It is  
determined by closure scope instead.
- don’t need a special “initialize” method. You put this  
functionality at the top-level of the “class” definition instead.
- instance variables are completely private. You could even have base  
and derived classes with instance variables of the same name and they  
won’t collide. Of course you might consider this a disadvantage when  
you want a derived class to access an instance variable of a base  
class, but this can be done by providing methods to the instance  
variables.

Here is a simple example:

class Object  
# are we ever going to get the fundamental method built-in to  
Object?  
def metaclass  
class\<\<self;self;end  
end  
# this would be great to have by default too.  
def define\_method(name, &block)  
self.metaclass.send(:define\_method, name, &block)  
end  
end

# conventional class

class Employee1 \< String  
@@id = 0  
def initialize(name)  
super(name)  
@id = @@id  
@@id += 1  
@salary = 0  
end  
def self.id(); @@id; end  
def id(); @id; end  
def salary(); @salary; end  
def hire(salary); @salary=salary; end  
def raise(inc); @salary+=inc; end  
def fire(); @salary=0;end  
end

# closure “class”

next\_id = 0 # class variable: all Employee2 methods/closures share this  
Employee2 = proc { |name|  
this = String.new(name) # inherits methods from String  
id = next\_id # instance variable: methods/closures of this object  
share this  
next\_id += 1  
salary = 0 # instance variable: methods/closures of this object  
share this  
this.define\_method(:id) { id }  
this.define\_method(:salary) { salary }  
this.define\_method(:hire) { |s| salary = s }  
this.define\_method(:fire) { salary = 0 }  
this.define\_method(:raise) { |inc| salary += inc }  
this  
}  
Employee2.define\_method(:id) { next\_id } # class method

e1 = Employee1.new(“bob”)  
e2 = Employee1.new(“john”)  
e3 = Employee1.new(“sally”)

e1.hire(20)==20  
e3.hire(25)==25

e1==“bob” and e1.salary==20 and e1.id==0 or raise(e1)  
e2==“john” and e2.salary==0 and e2.id==1 or raise(e2)  
e3==“sally” and e3.salary==25 and e3.id==2 or raise(e3)  
Employee1.id==3 or raise

e1 = Employee2.call(“bob”)  
e2 = Employee2.call(“john”)  
e3 = Employee2.call(“sally”)

e1.hire(20)==20  
e3.hire(25)==25

e1==“bob” and e1.salary==20 and e1.id==0 or raise(e1)  
e2==“john” and e2.salary==0 and e2.id==1 or raise(e2)  
e3==“sally” and e3.salary==25 and e3.id==2 or raise(e3)  
Employee2.id==3 or raise
