From: Robert Klemme Date: 2009-10-13T23:46:30+09:00 Subject: Re: Class Level inheritable attributes - are we there yet? 2009/10/13 Dreamcat Four : > Tom Stuart wrote: >>> else. >> Isn't this covered by the below? Not sure how class level attributes >> would give an advantage in this case. > > Writing the analogy out in Ruby isn't much help here. The construct you > are showing is just the familiar method-based and pattern is a method > for performance reasons that you should prefer it. We don't argue that > point. > > However by employing such the constructor chain, the species/class > definition is entirely static and not part of it can ever change. Its > brittle and fragile, and cannot adjust to / survive with changing > conditions in its environment. Of to put it another way - you cannot > append or overload a constructor funtion at runtime without destroying > entirely destroying the original constructor definition. > > > In Ruby, a class is defined as an object and therefore is free to change > its attributes over time. So there's no barrier in the Ruby language to > say "you must define your attributes wholely in the constructor and only > ever in the constructor function". > > > The real problem we are trying to address is that for the Library > writer, who will write a library of objects that behind it shall use the > constructor paradigm for many thing. But there are just a few things > which are sitting behind that in some stateful resource. (and are used > by, say 60% all object). To represent some stateful resource (endpoint > which may or may not exist) in such a brittle and inflexible way is > problematic. Essentially the constructor paradigm forces you to return > to method-based and functionally - oriented solutions. > > Think about an microprocessor board, which has 5 type of io > communications port. Lets say these are RS232, USB1, USB2, LPT, and > Bluetooth. Now do you represent those as a collection of 5 sets of > methods? or as 5 stateful io_port objects? > > 5 io_port objects, right? But in your constructor, you would have to > call another method elsewhere to query which ports existed in the middle > of runtime. With a class attribute, you wouldn't. The appropriate > resource method would be called once only (when the library was first > loaded into memory and the port object instantiated). Erm, aren't you mixing class and instance state here? If you have a Board class then that does not have any IO port objects, only instances have - and there would be IO port classes. Each board instance needs its own IO port objects because only those instances can be connected with a cable to some other port. This means, the constructor of Board would instantiate all the port instances. And this would be done in a regular instance method (#initialize). If you have variants of your Board then it depends on the application design. You might have multiple Board classes (one for each variant) which would create a different number of port objects each. Or you might provide some arguments to the constructor which would allow for variations. You could even store IO port classes per Board class and subclasses and provide initialization code which handles it, e.g. class Board IO_PORT_TYPES = [IOP1, IOP2] def initialize @io_ports = self.class::IO_PORT_TYPES.map {|cl| cl.new} end end class FooBoard < Board IO_PORT_TYPES = [IOP1, IOP2, IOP3] end irb(main):015:0> Board.new => #, #]> irb(main):016:0> FooBoard.new => #, #, #]> You can even change those arrays of classes at runtime and thus have the dynamic behavior - and inheritance because that is taken care of by Ruby's constant lookup mechanism. > Thats a 'too clean' and over-simplified example. Things actually are > much more tricky than that in real libraries. The paradigm also holds > true for many different types of resource used by a library. But this is a problem. As long as we do not get to the meat of the real problem you are trying to solve we cannot come up with a solution. It seems you have something in your mind but I for my part cannot claim that I fully understood what that is. Without that understanding it's difficult to have a discussion about this. I do not see a realistic use case which demands for class instance variables plus inheritance and which cannot easily be covered by existing mechanisms. Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/