I don't find much call for the animal -> dog -> retreiver either What I do find is a use for it at a more abstract level. My beans all inherit from a Base.Bean where I have common things to all beans (like onMissingMethod() that replaces all the dumb getters and setters in CF8), Base.DAO, Base.Service etc etc where all the common stuff is moved out of the 'concrete' classes (I know we're cf but its still a good way to describe them :-) ) into the abstract base classes. I would never create an instance of any of these base classes as they are meaningless on their own.
If you're learning OO I would focus less on all this inheritance stuff and look more at some other OO principles - encapsulation is an important one and is more wide-ranging than just getters and setters to encapsulate data, composition over inheritance, cohesion, loose coupling etc. Alan ________________________________________ From: [email protected] [EMAIL PROTECTED] On Behalf Of Nando [EMAIL PROTECTED] Sent: 02 May 2008 21:18 To: [email protected] Subject: [CFCDEV] Re: accessing sub-class methods No, animal -> dog -> retriever doesn't happen, especially in ColdFusion development for the web! Neither does my Father > Child example. I think I know how you feel. Inheritance is supposed to be there, so you look for it to show up in your design. If you come across a use case where you see you would repeat the same methods in a set of classes, that might be a good situation to use inheritance in ColdFusion at this point. You can create a super-class and put those repeated methods there, and then all the subclasses can use them, and you don't have to repeat them in each class. Some patterns in the OO world simply exist because of strict typing, and then type inheritance plays an important role. So you'll see a lot of examples using inheritance in OO literature, because it assumes strict typing. ColdFusion is more flexible because it is not strictly typed. Somewhere on your way to becoming a world class OO expert, you may begin typing your components in CF, but you'll know why you are doing it, and you will have made that choice wisely. You'll probably be working with a team, or providing an API, and not overly concerned about the performance hit. But to begin with, I don't think you should be using strict typing just yet, or trying to deal with patterns that require type inheritance. Get some experience under your belt first. If you pass an object into a function, use type="any", or type="component" if you want to ensure a component gets passed in. The consensus in CF development seems to have become that rather than trying to mimic the way things are done in a strictly typed language, leverage the fact that CF is loosely typed to your advantage, to save time and reduce complexity. If the added complexity of introducing typing and patterns that utilize type inheritance works toward your advantage, again, by the time you get there, you'll know exactly why you want to use that approach. Until then, you'll probably almost always use composition, except in the case i've outlined above. Nando It seems actually having use cases for the animal -> dog -> retriever type of relationship doesn't happen all that often. At least it hasn't in my app yet. On May 2, 11:28 am, Nando <[EMAIL PROTECTED]<mailto:[EMAIL PROTECTED]>> wrote: > The part about PaternalLine tries to explain how the term "inheritance" came > about. In the example, I'm probably mixing in too many concepts at once, and > not doing a good enough job of explaining them in separate examples. Sorry. > Let's leave that aside for a moment. > > To my mind, you can go 2 ways. One is that you can use inheritance, but then > you'll need to instantiate ImageService, and probably create a few other > similar objects like TextService for instance to handle text. ContentService > would most likely NOT be instantiated. Content Service would contain methods > common to handling both text and images, whereas TextService would contain > methods specific to text (if there are any), and ImageService would handle > methods specific to images. If that sounds appropriate, then you'd use > inheritance and place the extends attribute in TextService and ImageService > > <cfcomponent displayname="TextService" extends="ContentService"> > > Again, to use inheritance, you'll need to refactor your application to > instantiate TextService and Image Service, rather than ContentService. > > If you want to stick with using Content Service, then you'll need to either > pass an instance of ImageService into ContentService, or create an instance > of ImageService inside ContentService, most likely when ContentService is > instantiated. > > Are you clear how to do that yet? > > On Fri, May 2, 2008 at 4:11 PM, [EMAIL PROTECTED]<mailto:[EMAIL PROTECTED]> > <[EMAIL PROTECTED]<mailto:[EMAIL PROTECTED]>> > wrote: > > > > > Ok so using this PaternalLine idea, in the parent (which for me is > > contentService) it still needs an instance of the child (imageService) > > in order to perform any of its functions. > > > How does the child perform a function of the uncle when they are both > > essentially children of PaternalLine? This is how I see the > > relationshis the way you explain it, looking just at inheritance: > > PaternalLine -> Father -> Child > > PaternalLine -> Uncle > > > The way I see this the child still needs an instance of uncle in order > > to perform its functions. So essentally this isn't inheritance > > anymore, its composition... Please explain further if It seems that I > > am missing something. > > > On May 1, 7:14 pm, Nando <[EMAIL PROTECTED]<mailto:[EMAIL PROTECTED]>> > > wrote: > > > You have a class called ContentService. You notice that besides dealing > > in > > > generic ways with content, it's beginning to deal in specialized ways > > with > > > with various types of content. > > > > You can then refactor your application and shift the specialized methods > > > into classes that extend Content Service, let's call them TextService, > > > ImageService and FlashService. Then you have the following components: > > > > <cfcomponent displayname="ContentService"> > > > <cffunction name="ProcessAllTypesOfContent"> > > > </cffunction> > > > </cfcomponent> > > > > <cfcomponent displayname="TextService" extends="ContentService"> > > > <cffunction name="ProcessText"> > > > </cffunction> > > > </cfcomponent> > > > > <cfcomponent displayname="ImageService" extends="ContentService"> > > > <cffunction name="ProcessImage"> > > > </cffunction> > > > </cfcomponent> > > > > <cfcomponent displayname="FlashService" extends="ContentService"> > > > <cffunction name="ProcessFlash"> > > > </cffunction> > > > </cfcomponent> > > > > How your application would work now is that instead of instantiating > > > ContentService to process content, you'd instantiate the specialized > > class > > > instead, let's say ImageService. The extents attribute on ImageService > > makes > > > the functions in ContentService available in ImageService. So in our > > simple > > > example, you'd call imageService.ProcessImage() method first, and then > > the > > > imageService.ProcessAllTypesOfContent() method to finish the job, all > > from > > > ImageService. The variables scope within ImageService would be available > > to > > > the ContentService's methods. > > > > That's all that inheritance does. > > > > The term "inheritance" for someone new to this can seem like it > > > *should*mean that the parent passes on its knowledge and wealth to the > > > child, but > > > that ain't how it works. The child can use the parent's knowledge, but > > > doesn't get its instance data. > > > > So you always instantiate the "child" object, the one with the extends > > > attribute, to get the job done. The "parent" doesn't know a thing about > > the > > > "child". If you instantiate the parent object, it cannot use the child's > > > methods or instance data, and in fact has no awareness that it even > > *has* a > > > child. > > > > If you are one of those persons who wish that their father took a more > > > active role in your life and tend to design your applications to try and > > > make up for it, then here is what you must do ;-) > > > > <cfcomponent displayname="Father" extends="PaternalLine"> > > > > <cffunction name="CreateChild"> > > > <cfset var Child = CreateObject("component", Child).init(this) > > /> > > > <cfreturn Child /> > > > </cffunction> > > > > <cffunction name="UseTheCar"> > > > </cffunction> > > > > <cffunction name="UseCreditCard"> > > > </cffunction> > > > > </cfcomponent> > > > > <cfcomponent displayname="Child"> > > > <cffunction name="init"> > > > <cfargument name="Father" required="yes" type="PaternalLine" /> > > > <cfset variables.Father = arguments.Father /> > > > <cfreturn this /> > > > </cffunction> > > > > <cffunction name="DriveCar"> > > > <cfreturn variables.Father.UseTheCar() /> > > > </cffunction> > > > > <cffunction name="BuyNewMac"> > > > <cfreturn variables.Father.UseCreditCard() /> > > > </cffunction> > > > > </cfcomponent> > > > > In the above example, when the Father creates the Child, notice that we > > have > > > passed "this" into the init() method of the Child, which in effect > > passes > > > all of the Father's knowledge and instance data into the child. It's > > still > > > encapsulated within Father, but the Child can make use of it by calling > > > Father and saying, "Dad, can I have the car keys? I want to go downtown > > and > > > pick up that new MacBook Pro you promised me!" > > > > In our example above, notice also that Father extends an object called > > > PaternalLine. Notice also that the init() method in Child only accepts > > an > > > object with the type "PaternalLine" as a Father. In this case, Father > > has * > > > inherited* the type PaternalLine, and what this arrangement allows is > > that > > > the Child can also borrow the Uncle's car and use his credit card. His > > Uncle > > > can stand in as his Father, because his Uncle also extends the > > PaternalLine. > > > The term inheritance refers originally to this mechanism of *type > > > inheritance*. > > > > <cfcomponent displayname="Uncle" extends="PaternalLine"> > > > > <cffunction name="CreateNephew"> > > > <cfset var Child = CreateObject("component", Child).init(this) > > /> > > > <cfreturn Child /> > > > </cffunction> > > > > <cffunction name="UseTheCar"> > > > </cffunction> > > > > <cffunction name="UseCreditCard"> > > > </cffunction> > > > > </cfcomponent> > > > > In languages that use strict typing such as Java, type inheritance is > > very > > > important. It allows you to program your app so that the Child can go to > > > either his Father or Uncle to use the car, for instance. ColdFusion, > > because > > > it's not strictly typed, doesn't need the mechanism of inheritance to > > > provide this flexibility. You can just use type="any". So in ColdFusion, > > > unless you're traveling the strictly typed road to ensure that the > > Children > > > in your application only ask family members to use the car for instance, > > > inheritance is much less important than it seems to be from reading > > pattern > > > books and hanging out with people who learned object orientation using a > > > strictly typed language. > > > > I hope my example is clear enough ... and doesn't have any glaring > > flaws. > > > > Nando > > > > On Thu, May 1, 2008 at 9:52 PM, Alan Livie <[EMAIL > > > PROTECTED]<mailto:[EMAIL PROTECTED]> > > > > wrote: > > > > > I'll say again I'm no expert but I'm not sure it's a good hierarchy > > you're > > > > embarking on (but its hard to tell with no details) and think your > > > > ContentService should probably have an association to an ImageService > > > > instead. > > > > Then your contentService would just use <cfreturn > > > > variables.ImageService.getImageByGallery() /> > > > > This also means you can use your imageService in other services using > > the > > > > same association. > > > > > Although the sentence 'an image service IS-A content service' sounds > > > > correct in the real world it doesn't mean it works at a design level. > > If > > > > your contentService is full of methods that your ImageService can use > > then > > > > perhaps it is a candidate for a parent / child relationship. > > > > If ImageService would only ever use one or two of ContntService's > > methods > > > > then it definately IS NOT a good candidate for a subclass. > > > > > And thinking along the lines of parents accessing methods in a > > subclass I > > > > don't think helps either. A good way that inheritance hierarchies > > evolve is > > > > when you have a class then you realise you need something similar but > > > > slightly different. Then you realise that some methods in both classes > > can > > > > be shared. Then you refactor by creating a parent class, copying the > > dupe > > > > methods up into it and taking the dupes out of the child classes. Add > > an > > > > extends="path to parent" and you've refactored. And you'll want to > > unit test > > > > this all the way of course :-) > > > > > Hope this helps and I'm sure some will disagree with me! > > > > ________________________________________ > > > > From: [email protected]<mailto:[email protected]> [EMAIL > > > > PROTECTED]<mailto:[email protected]>] On Behalf Of > > > > [EMAIL PROTECTED]<mailto:[EMAIL PROTECTED]> [EMAIL > > > > PROTECTED]<mailto:[EMAIL PROTECTED]>] > > > > Sent: 01 May 2008 18:27 > > > > To: CFCDev > > > > Subject: [CFCDEV] accessing sub-class methods > > > > > I need to know if I can access the methods in a child object from its > > > > parent class and if so, how I might do that. > > > > > I > > ... > > read more ยป -- Nando M. Breiter The CarbonZero Project CP 234 6934 Bioggio Switzerland +41 76 303 4477 [EMAIL PROTECTED] --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "CFCDev" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/cfcdev?hl=en -~----------~----~----~----~------~----~------~--~---
