| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#11
| |||
| |||
| 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 |
|
#12
| |||
| |||
| 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 ptionsoptions[: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 |
|
#13
| |||
| |||
| 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. |
|
#14
| |||
| |||
| 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 |
|
#15
| |||
| |||
| 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 |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.