Class#inherited, class definition and industry.

C

Ceri Storey

--GvXjxJ+pjyke8COw
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi there.

Am I correct in thinking that the #inherited method of the parent class
is called *before* the body of the class is evaluated?

If so, is there a more sensible way of working around this, than
something like the following?
--
Ceri Storey <[email protected]>

--GvXjxJ+pjyke8COw
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="sample.rb"

class Builder
@registry = {}
@registered = []

class << self
def inherited(sub)
@registered.push(sub)
end

def lookup(name)
if @registry.include?(name)
@registry[name]
elsif c = @registered.find { |c| c.name == name }
@registry[c.name] = c
c
else
raise "No such Class"
end
end

def create(name, *args)
lookup(name).new(*args)
end
end
end

class Moogle < Builder
class << self
def name
"moogle"
end
end
end

Builder.create("moogle")

--GvXjxJ+pjyke8COw--
 
N

nobu.nokada

Hi,

At Tue, 25 Nov 2003 23:26:58 +0900,
Ceri said:
Am I correct in thinking that the #inherited method of the parent class
is called *before* the body of the class is evaluated?

Yes. The end of definition cannot be determined in Ruby.
If so, is there a more sensible way of working around this, than
something like the following?

I thought of similar one formerly, and still haven't get better
one.

Well, how about #singleton_method_added, if you use particular
singleton method as the key?
# But note that Module#name is pre-defined method.

class Builder
@@registry = {}
class << self
def singleton_method_added(name)
@@registry[send(name)] = self if name == :name
super
end

def lookup(name)
@@registry.fetch(name) do
raise ArgumentError, "No such Class"
end
end

def create(name, *args)
lookup(name).new(*args)
end
end
end

class Moogle < Builder
def self.name
"moogle"
end
end

Builder.create("moogle")

Or, if names are always class names in lower case, you can use
the names even in #inherited.

class Builder
@registry = {}
class << self
def inherited(c)
@registry[c.name.downcase] = c
super
end

def lookup(name)
@registry.fetch(name) do
raise ArgumentError, "No such Class"
end
end
end

You can define Builder.name as returning lower case name and
use it too.

class Builder
@registry = {}
class << self
def name
super.downcase
end
def inherited(c)
@registry[c.name] = c
super
end
end
end

And another one, with http://nokada.jin.gr.jp/ruby/factory.rb

require 'factory'

class Builder
extend Factory
end

class Moogle < Builder
factory do |name, *args|
new(*args) if /\Amoogle\z/ =~ name
end
end

p Builder.create("moogle")
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top