Using strings for the roles is really just the simple version. So to extend your last paragraph there, in a real system, I would indeed have each role as a discreet object, and add those objects to the collection of roles instead of just using the strings. The strings were a convenience for the sake of demonstrating the concept of roles (or plugins, or whatever you want to call them) :)
Roland -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Barney Boisvert Sent: Wednesday, April 06, 2005 7:35 PM To: [email protected] Subject: Re: [CFCDev] Question on class / subclass This is exactly what interfaces are for: specifying behaviour for types, without requiring inappropriate inheritance hierarches. There's a reason every OO language has them; they're damn near essential for good OO design. Maybe I'm missing something, or maybe it's just personal style, but I don't see any value to definine these "things" (be they interfaces or roles) in code, rather than in metadata where they belong. With the abstract behaviours, you're packaging the functionality up in a resuable way, but you're still not providing any means of determining if a given instance of Vehicle (or whatever the top-most type is) has the ability to tow a boat. And even at that, you still have to have all those individual classes anyway, because each one will have a different init method (for creating the various behaviours it has) and different get/set/do methods for each behaviour. Now if we were instead to define "plugin" points for the Car class, and then each car instance could be dynamically extended at runtime with specific behaviour (i.e. add a trailer hitch or a supercharger), then we'd be getting somewhere. You'd still have to have a pretty complex set of base classes, but you could reduce the number significantly, and keep your application flexible to future changes in car abilities. Each Car would have a boolean canDo(string:x) method or something, which would return if the instance could do the specific task, whether it was a built-in function or an dynamic add-on. cheers, barneyb On Apr 6, 2005 4:12 PM, Joe Rinehart <[EMAIL PROTECTED]> wrote: > I think Roland's method is definitely a move in the right direction. > > In fact, I'd probably throw out inheritance altogether - what defines > a "car" or a "truck" and what capabilities each has is a shift > subject...some cars can tow, and some trucks can move pretty quickly. > Before long, we may have Car, Truck, CarThatCanTow, > TruckThatCanGoFast, ConvertibleCar, ConvertibleTruck (blame > chevrolet), TwoDoorCar (not convertible!), TwoDoorTruck, > ConvertibleTwoDoorCar, and...well...crap, that's a lot of maintenance. > > I think one way to approach it would be to implement each behavior > (towing, going fast, being able to put the top down (which some wacky > chevy "trucks" can do), etc.) as an "abstract" class, and when a "car" > is created (probably by a factory), it just gets composed of the > proper concrete implementations of the behaviors. I think some people > lump this together under the general monicker of the "Behavior" > pattern. > > (I shortcut and assign the abstractTow and abstractSpeed behaviors > because, well, we can in CF, and I just have the abstract ones throw > errors if they get executed.) > > It'd look something like this: > > <cfcomponent name="car"> > <cffunction name="init"> > <cfset variables.towBehavior = createObject("component", > "abstractTow").init()> > <cfset variables.speedBehavior = createObject("component", > "abstractSpeed").init()> > </cffunction> > > <!--- Getters and setters for towBehavior / speedBehavior ---> > > <!--- /Getters and setters for towBehavior / speedBehavior ---> > > <!--- Returns towing capacity - not necessarily a number, may be an object! ---> > <cffunction name="doTowBehavior"> > <cfreturn variables.towBehavior.doSomething() /> > </cffunction> > > <!--- Returns information about speed - not necessarily a number, may > be an object! ---> > <cffunction name="doSpeedBehavior"> > <cfreturn variables.towBehavior.doSomething() /> > </cffunction> > > </cfcomponent> > > ...the implementation is way incomplete, and in reality, may be a lot > more complex, with the behaviors acting on / interacting with the > "mother" object, possibly through package-only methods, etc. What's > important is that we're moving away from inheritence, which locks us > into a given set of behaviors at compile-time, and moving towards > runtime composition, where we can "build" objects that perform in a > given way at will. > > It does, though, have consequences. If suddenly we get a rash of cars > that have five wheels, we'll have to go add a new property to the Car. > However, because we don't have a complicated inheritance tree, we > don't wind up impacting a gazillion other implementations of cars. > Heck, maybe that's more of an advantage that a consequence. I'm sure > someone else can point out a downside to this approach. > > -Joe -- Barney Boisvert [EMAIL PROTECTED] 360.319.6145 http://www.barneyb.com/ Got Gmail? I have 50 invites. ---------------------------------------------------------- You are subscribed to cfcdev. To unsubscribe, send an email to [email protected] with the words 'unsubscribe cfcdev' as the subject of the email. CFCDev is run by CFCZone (www.cfczone.org) and supported by CFXHosting (www.cfxhosting.com). An archive of the CFCDev list is available at www.mail-archive.com/[email protected] ---------------------------------------------------------- You are subscribed to cfcdev. To unsubscribe, send an email to [email protected] with the words 'unsubscribe cfcdev' as the subject of the email. CFCDev is run by CFCZone (www.cfczone.org) and supported by CFXHosting (www.cfxhosting.com). An archive of the CFCDev list is available at www.mail-archive.com/[email protected]
