From: Luke Kanies Date: 2005-07-12T10:06:38+09:00 Subject: Re: class_attr_accessor On Tue, 12 Jul 2005, Ara.T.Howard wrote: > it just ducks into the singleton class of whatever object you use it on. in > the case the object is a class and it just so happens that class methods are > singleton methods of classes so you end up defining class methods this way Ok. [...] > using this construct in classes just so happens to work nicely since singleton > methods of classes are also know as 'class methods' for instances of that > class. Ok, just making sure. > there's no need really - but it allows you to do things like this that cannot > be done otherwise: > > class C > class << self > attr 'a' > attr 'b' > alias c a > alias d b > end > attr 'a' > attr 'b' > end > > so now we have instance method 'a' and 'b' and class methods 'a' and 'b' and > aliases for those two class methods 'c' and 'd' respectively. because the > 'attr' and 'alias' calls are in class singleton scope here it works. Yeah, that's what I'll be using, since it should work just fine for my purposes, but I think it's a touch obfuscated. Of course, I've already admitted to not fully grokking the 'class << self' syntax, so that doesn't help. > if they don't it's doubtful that they are real subclasses. most OO theory > would suggest that any subclass (subtype) is a specialzation only of the > base class - eg it should only ADD new behaviour. be definition that means > any existing class vars should be inherited. if you aren't inheriting class > vars (and therefore clobbering them) you might want to look at other code > sharing methods like mixins since you may not have a true inheritence > hierarchy. I agree, I probably don't have "valid" heirarchies. I would probably describe most of my heirarchies with a type at the type, and then instances of that type below it, and then instances of those instances below that. For instance (similar to the other example I just sent): class Type class << self attr_accessor :params end # class method def self.each unless defined? @params raise "@params not defined for %s" % self end @params.each { |param| yield param } end def []=(param,value) @params[param] = value end def [](param) @params[param] end # instance method; notice this is a hash, not an array def each unless defined? @params raise "@params not defined for %s" % self end @params.each { |param,value| yield param, value } end def initialize(hash) @params = {} self.class.each { |param| if hash.include?(param) self[param] = value hash.delete(param) else raise "%s requires parameter %s" % [self.class, param] end } if hash.length > 0 raise "Unknown parameter(s) '%s'" % hash.keys.join(" ") end end end class Sub < Base @params = [:name, :address] end instance = Sub.new( :name => "Luke", :address => "42 Earth" ) I really feel like this is a type at the top, with an instance of the Base class below that, and then an instance of the instance below that. I expect that I'm being retarded here, and there's some significantly better way of doing this, but it's working pretty darn well for me, so I'm sticking with it unless someone else has a better idea. > of course most of my inheritence hierarchies aren't technically 'valid' either > ;-) Not that I'd know how to tell... > you have that already > > class C > class << self > attr 'foo' > end > end Yah, and that's what I'll be using now that I (basically) understand it, but I still think it's pretty obfuscated. > > I'll check into 'traits', but I don't think I can use it for this > > project, since I have to mostly stick to libs that are part of the > > standard library. > > it's pure ruby so you can always just cut and paste it. ;-) The above is sufficient for now, but we'll see. Thanks, Luke -- Writing is not necessarily something to be ashamed of, but do it in private and wash your hands afterwards. --Robert Heinlein --------------------------------------------------------------------- Luke Kanies | http://reductivelabs.com | http://config.sage.org