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]