On Sat, 22 Jan 2005 06:53:45 +0900, Anders Engströí <aengstrom / gnejs.net> wrote:
> Another option is to use the :new method on the class to implement the
> class Section
> 
>     class << self
>         # Called to get (or create) new instance
>         def new(id)
>             cached_instances()[id] || cached_instances()[id] = super
>         end
> 
>         def cached_instances()
>             @cache = {} unless @cache
>             @cache
>         end
>     end
> 
>     # Called on new instance
>     def initialize(id)
>         puts "Creating a new instance"
>         @id = id
>     end
> 
> end

Equivalent, but somewhat more concise and rubyish (IMO):

class Section
    class << self
        # Called to get (or create) new instance
        def new(id)
            cached_instances[id] ||= super
        end

        def cached_instances
            @cache ||= {}
        end
    end

    # Called on new instance
    def initialize(id)
        puts "Creating a new instance"
        @id = id
    end
end

Changes:
1) The ||= operation is very useful for defaults. The statement

  a ||= b

simply expands to

  a = a || b

which is equivalent to the

  a || a = b

that you had written. It is also equivalent to the

  a = b unless a

which you had in the second function.

2) An empty parameter list is usually unnecessary, thus you can both
define and call cached_instances without needing the '()'. Attaching
an empty parameter list differs from no parameter list in only two
cases I can think of; a) super vs. super() and b) disambiguating
between a local variable and method of the same name (this may not
even be an issue).

3) The return value of a ||= b is the new value of a (either what it
was, or b if it didn't have a previous value), so the explicit mention
of @cached as the return value is unnecessary in cached_instances.

Jacob Fugal