From: Gavin Kistner Date: 2004-09-23T23:46:15+09:00 Subject: Design Advice: Sub-Class 'Instances' --Apple-Mail-2--468029632 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; format=flowed Summary I'm looking for advice on how to design code so that I can dynamically add/remove instantiable classes, where each of these classes have values for a set of properties defined by a parent class. Details I'm starting to design/write an uber-ambitious home automation hub, in Ruby. In addition to having convenient things like a web-based GUI front-end, scheduler, and so on, the heart of this application is that it will (eventually) work with any automation hardware whose communication protocol is open (or reverse-engineered). The plan is to have 'adaptors' for each discrete hardware type, which encapsulate all the guts of the communication protocol and expose methods for that bit of hardware. The user can then 'instantiate' one or more of these adaptors, representing physical instances of that bit of hardware in the home. (For example, there's a single "Lutron RadioRA Wall Dimmer" adaptor, but the user may have 4 such switches in the house, named "Front Kitchen Lights", "Rear Kitchen Lights", "Bedroom Lights", and "Entry Lights".) In addition to custom methods, each adaptor needs to expose some common information, such as its name, manufacturer, category, sub-category, model number, and so on. I initially decided to have code like this: me = Foo::Bar::DeviceType.new( 'Lutron RadioRA Wall Dimmer', :Lutron, :Switches, :Dimmers, 'RA-ND6' ) me.add_action( :turn_on, Proc.new{ ... } ) me.add_action( :turn_off, Proc.new{ ... } ) me.add_action( :level=, Proc.new{ ... } ) me.add_action( :level, Proc.new{ ... } ) #...and then later do something like... Foo::Bar::add_device( 'Entry Lights', blah ) # ...where blah is a pointer to the DeviceType instance But then I realized that I'm mostly just putting a wrapper around a class definition. Further, I realized that I want all adaptors to support common methods (name, manufacturer, model number), all light switches to support some common methods (turn_on, turn_off), and all dimmers to support others still (level= and level). This reeks of a class hierarchy, so I was thinking that I might do something like: # Core app class Foo::Bar::DeviceType def name; raise "Implement Me!"; end def manufacturer; raise "Implement Me!"; end def model; raise "Implement Me!"; end class Light def turn_on; raise "Implement Me!"; end def turn_off; raise "Implement Me!"; end class Dimmer def level=(n); raise "Implement Me!"; end def level; raise "Implement Me!"; end end end end #Adaptor file class Foo::Bar::DeviceType::Light::Dimmer::RadioRA def name; 'Lutron RadioRA Wall Dimmer'; end def manufacturer; 'Lutron'; end def name; 'RA-ND6'; end def turn_on; ...; end; def turn_off; ...; end; def level=(n); ...; end; def level; ...; end; Foo::Bar::DeviceType::add_device( self ) end ... and the add_device method would a) Create a dummy parent class and run through all the methods to see if they throw errors. b) Add the class into a list of instantiable adaptors if it works. Questions 1) Is there a way to inspect the runtime state and figure out which subclasses exist for a given class? 2) Is there a better way to force/detect if a subclass implements certain methods? 3) Is there a better way overall to achieve my goal? Thanks if you even read this far. Thanks even more if you take the time to think about the problem and offer suggestions. -- (-, /\ \/ / /\/ --Apple-Mail-2--468029632--