Difficult Inheritance Problem

This is a discussion on Difficult Inheritance Problem within the RUBY forums in Programming Languages category; On Wed, Aug 27, 2008 at 2:55 PM, David A. Black <dblack @ rubypal.com> wrote: > Hi -- > > On Wed, 27 Aug 2008, Robert Dober wrote: > >> On Wed, Aug 27, 2008 at 1:37 PM, David A. Black <dblack @ rubypal.com> >> wrote: >> Wow that is great, I would call them viral class variables! > > I think class variables are already viral :-) Well they are unique, applying your pattern however the following holds class X < Page @difference_mapping = 42 end Y = Class::new( X ) Y.difference_mapping => 42 *while* Next.difference_mapping is still the ...

Go Back   Application Development Forum > Programming Languages > RUBY

Object Mix

Register FAQ Calendar Search Today's Posts Mark Forums Read
  #11  
Old 08-27-2008, 11:54 AM
Robert Dober
Guest
 
Default Re: Difficult Inheritance Problem

On Wed, Aug 27, 2008 at 2:55 PM, David A. Black <dblack@rubypal.com> wrote:
> Hi --
>
> On Wed, 27 Aug 2008, Robert Dober wrote:
>
>> On Wed, Aug 27, 2008 at 1:37 PM, David A. Black <dblack@rubypal.com>
>> wrote:
>> Wow that is great, I would call them viral class variables!

>
> I think class variables are already viral :-)

Well they are unique, applying your pattern however the following holds

class X < Page
@difference_mapping = 42
end

Y = Class::new( X )

Y.difference_mapping => 42
*while*
Next.difference_mapping is still the hash.
-----------------------------------------------------

I meant with viral that the *new* values are propagated *only* down
the inheritance tree that is what OP wanted and I have to admit I did
not see immediately that your solution was correct in that regard.
When I realized how it was I found it quite amazing.

I should have said that self.inherited was viral.

Cheers
Robert

Reply With Quote
  #12  
Old 08-28-2008, 01:59 AM
Joel VanderWerf
Guest
 
Default Re: Difficult Inheritance Problem

Toby Clemson wrote:
> Is there a way to define a class level variable that descends down the
> inheritance tree unless it is overridden in the same way as this is
> possible for methods?


Yes, using a hash that inherits values:

http://redshift.sourceforge.net/superhash/
http://redshift.sourceforge.net/supe...superhash.html

Sorry for the crappy docs. It's an old project, but I use it frequently.

Here's an example

require 'superhash'

class A
class_superhash ptions

options[:foo] = "A foo"
options[:bar] = "A bar"

def options; self.class.options; end
end

class B < A
options[:foo] = "B foo"
end

p A.options
p B.options.to_hash
p B.new.options.to_hash

__END__

output:

{:foo=>"A foo", :bar=>"A bar"}
{:foo=>"B foo", :bar=>"A bar"}
{:foo=>"B foo", :bar=>"A bar"}

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Reply With Quote
  #13  
Old 08-29-2008, 12:45 AM
David Masover
Guest
 
Default Re: Difficult Inheritance Problem

On Wednesday 27 August 2008 06:44:46 James Coglan wrote:
> >
> > The easiest way I can think of is:
> >
> > class Page
> > class << self
> > attr_accessor :difference_mapping
> > end
> > def self.inherited(c)
> > c.difference_mapping = difference_mapping
> > end
> > end
> >
> > Page.difference_mapping = { :blah => :blah }
> >
> > class Next < Page
> > end
> >
> > p Next.difference_mapping # { :blah => :blah }

>
>
>
> Depends whether you only need the definition done once. This technique will
> not cause the subclass to reflect the parent class' value if it is changed,


In that case, let me take a shot:

class Page

class << self
attr_accessor :difference_mapping
end

module DescendantClassMethods
def difference_mapping
Page.difference_mapping
end
def difference_mapping= value
Page.difference_mapping = value
end
end

def self.inherited klass
klass.extend DescendantClassMethods
end
end


Since I'm in a late-night hacking mood, here's a way that's even more meta:

# because << drives me crazy
require 'metaid'

# name it whatever you want...
module ClassVariables
module BaseClassMethods
def class_variable name
self.meta_eval do
attr_accessor name
end
superclass = self
(self::InheritableClassVariables ||= Module.new).module_eval do
define_method name do
superclass.send name
end
assignment = :"#{name}="
define_method assignment do |value|
superclass.send assignment, value
end
end
end

def inherited klass
mod = self::InheritableClassVariables
# I think this, instead of extend, will let subclasses override
# these methods properly.
klass.meta_eval do
include mod
end
end
end

def self.included mod
mod.extend BaseClassMethods
end
end



Hmm. That's... mostly complete. Usage would be:

class Page
include ClassVariable
class_variable :difference_mapping
end

But I haven't so much as executed it to check for syntax errors.

Reply With Quote
  #14  
Old 09-02-2008, 08:01 AM
tobyclemson@gmail.com
Guest
 
Default Re: Difficult Inheritance Problem

Thank you all for your responses. I ended up using James Coglan's
solution as that is what I was trying to achieve even if I didn't make
that clear in my first post. But even so I've learnt something from
each of your responses.
Cheers,
Toby
Reply With Quote
  #15  
Old 09-02-2008, 08:19 AM
Robert Klemme
Guest
 
Default Re: Difficult Inheritance Problem

2008/9/2 tobyclemson@gmail.com <tobyclemson@gmail.com>:
> Thank you all for your responses. I ended up using James Coglan's
> solution as that is what I was trying to achieve even if I didn't make
> that clear in my first post. But even so I've learnt something from
> each of your responses.


I believe there is a better approach that solves the inheritance issue
generally. (Jame's solution will only reuse mappings as long as no
mapping is defined in the current class.) Usually you want to deal
with all the mappings aggregated so far in the inheritance hierarchy.
Thus my solution would be

class DataObject
class<<self
attr_writer :difference_mapping

def difference_mapping
ancestors.inject({}) do |m,cl|
m.merge(cl.instance_variable_get("@difference_mapp ing")) rescue m
end
end
end
end

class Page < DataObject
self.difference_mapping = {:blah => :blah}
p [self, difference_mapping]
end

class YourClass < Page
p [self, difference_mapping]
end

Kind regards

robert


--
use.inject do |as, often| as.you_can - without end

Reply With Quote
Reply


Thread Tools
Display Modes


All times are GMT -5. The time now is 08:31 PM.


Powered by vBulletin® Version 3.7.2
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
vB Ad Management by =RedTyger=

In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.