Race condition in class inheritance

G

Gaspard Bucher

I need to identify classes from a string called kpath (class path)
reflecting the class inheritance. The string is made of the first
letter of each class. This is what I have now:
class Node
@@classes = {'N' => self}
def self.inherited(child)
super
@@classes[child.kpath] = child
end

def self.kpath
self == Node ? ksel : (superclass.kpath + ksel)
end

def self.ksel
self.to_s[0..0]
end

def self.class_from_kpath(kpath)
@@classes[kpath]
end
end

class Page < Node
end

class Document < Page
end

class Draft < Page
def self.ksel
'A'
end
end

puts Node.class_from_kpath('N') # got 'Node', ok.
puts Node.class_from_kpath('NPD') # wanted 'Document', got 'Draft'
puts Node.class_from_kpath('NPA') # wanted 'Draft', got nil

I understand that Draft's ksel method is not known at the time
Node.inherited is called.

How can I have Node.inherited being called once the complete child
class is built ?

Thanks for your answers.
Gaspard
 
J

Joel VanderWerf

Gaspard said:
I need to identify classes from a string called kpath (class path)
reflecting the class inheritance. The string is made of the first
letter of each class. This is what I have now:

Defer building the hash until class_from_path is called.

One quick and dirty set of changes that does it:
class Node
@@classes = {'N' => self}
Replace:

def self.inherited(child)
super
@@classes[child.kpath] = child
end

With:

@@unhandled_children = []
def self.inherited(child)
super
@@unhandled_children << child
end

def self.kpath
self == Node ? ksel : (superclass.kpath + ksel)
end

def self.ksel
self.to_s[0..0]
end

def self.class_from_kpath(kpath)

Add:

while child = @@unhandled_children.pop
@@classes[child.kpath] = child
end
@@classes[kpath]
end
end

class Page < Node
end

class Document < Page
end

class Draft < Page
def self.ksel
'A'
end
end

puts Node.class_from_kpath('N') # got 'Node', ok.
puts Node.class_from_kpath('NPD') # wanted 'Document', got 'Draft'
puts Node.class_from_kpath('NPA') # wanted 'Draft', got nil

I understand that Draft's ksel method is not known at the time
Node.inherited is called.

How can I have Node.inherited being called once the complete child
class is built ?

Thanks for your answers.
Gaspard
 
G

Gaspard Bucher

Thanks for the idea, that's a good workaround.

Gaspard

2007/9/14 said:
Gaspard said:
I need to identify classes from a string called kpath (class path)
reflecting the class inheritance. The string is made of the first
letter of each class. This is what I have now:

Defer building the hash until class_from_path is called.

One quick and dirty set of changes that does it:
class Node
@@classes = {'N' => self}
Replace:

def self.inherited(child)
super
@@classes[child.kpath] = child
end

With:

@@unhandled_children = []
def self.inherited(child)
super
@@unhandled_children << child
end

def self.kpath
self == Node ? ksel : (superclass.kpath + ksel)
end

def self.ksel
self.to_s[0..0]
end

def self.class_from_kpath(kpath)

Add:

while child = @@unhandled_children.pop
@@classes[child.kpath] = child
end
@@classes[kpath]
end
end

class Page < Node
end

class Document < Page
end

class Draft < Page
def self.ksel
'A'
end
end

puts Node.class_from_kpath('N') # got 'Node', ok.
puts Node.class_from_kpath('NPD') # wanted 'Document', got 'Draft'
puts Node.class_from_kpath('NPA') # wanted 'Draft', got nil

I understand that Draft's ksel method is not known at the time
Node.inherited is called.

How can I have Node.inherited being called once the complete child
class is built ?

Thanks for your answers.
Gaspard
 

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,776
Messages
2,569,602
Members
45,185
Latest member
GluceaReviews

Latest Threads

Top