Ask a Question related to Coldfusion - Advanced Techniques, Design and Development.
-
bhalper #1
CFC extends
I have an application which uses about 7 CFC's that takes care of all my
business logic. However they do not relate to each and i would like to improve
this by using inheritance. For instance (forgive the pun) each CFC has its own
init which sets the value of my DSN. I think it would make more sense to have
parent/constructor CFC which set up some variables, loads all the other cfc
which then extend to it. I have been doing some simple theoretical testing and
I cannot for the life of me get a child cfc to inherit variables set in the
parent.
**********Parent CFC*********
<cfcomponent displayname="main" hint="main cfc loads children">
<cfproperty name="this.dsn" type="string">
<cffunction name="init" access="public" returntype="any" output="no">
<cfargument name="dsn" required="yes" type="string">
<cfset this.dsn = arguments.dsn>
<cfset this.Child = CreateObject("component", "child")>
<cfreturn this>
</cffunction>
</cfcomponent>
*******CHILD CFC*******
<cfcomponent extends="main">
<cffunction name="returnthis" access="public" returntype="any">
<cfreturn this.dsn>
</cffunction>
</cfcomponent>
********CALLING PAGE*********
<cfscript>
main = CreateObject("component", "components.main").init("MyDsn");
dsn = main.Child.returnthis();
</cfscript>
<cfdump var="#dsn#">
**********************
As you can see i am simply to trying to get my child cfc to inherit the value
of mydsn and return it to the calling page. But whatever i do the result is
always an error, 'DSN is undefined in THIS.' I have changes the this scope to
variables and i have tried instantiating the child cfc separately from the main
cfc but with the same results.
Is this process correct? why doesn't this work?
Can cfc only inherit methods and not vars? Have i misinterpreted how
inheritance works?
bhalper Guest
-
How to extends a datagrid
Hi, I want to write my own datagrid. I defined it as: import mx.controls.DataGrid; class MyDataGrid extends DataGrid { } -
CFComponent extends confusion
Has any one figured out the proper behaviour of the EXTENDS attribute to CFCOMPONENT. I haven't been able to find out how this attribute is... -
class extends TextFields
I want to create a class that extends TextField, but there is no way (that I can see) to impliment this. I can't set the AS2.0 class the way I can... -
import and extends issue
I have a class that I declared in a file: Classes/charts/BaseChart.as as class charts.BaseChart { ... I then have a sub-class in file:... -
[PHP] PHP class and extends
You can do one of 2 things. 1. You can comment out the ExecuteQuery Function in the child class. 2. When you call the function in the child... -
mpwoodward *TMM* #2
Re: CFC extends
In your calling page code, first you create a main object. That's
fine. I think there's a bit of a disconnect in your understanding of
how inheritance works, however. At a very high level, don't for
inheritance into the picture if it isn't necessary. I understand your
goals with sharing the DSN setting method between the objects, but
overuse of inheritance is a pretty common issue when people are just
getting started with OOP.
Now as for the specifics of what's going on in your code, when you
create main.Child (as an aside, why are you doing that inside your main
object?), that just creates the object. It doesn't call any methods,
it doesn't set any variables, so when you call returnthis(), the dsn
won't exist in Child.
I think you're making a couple of assumptions that aren't correct about
how inheritance works. First, child objects do not inherit instance
variables from their parent. In other words, I think you're expecting
that because you create your main object and instantiate the child
object inside the main object that it will "know" what dsn is, and this
isn't the case. A child object will inherit methods and properties
from the parent, but not the VALUES of specific properties (variables)
from a specific instance of the parent object.
Second, when you create the child object it doesn't automatically call
methods in the parent object. If you want it to call methods and do
things, or set values of variables, you have to tell it to do that. In
your child object you have no init() method and you don't set any
variables, so when it gets instantiated it's literally an empty object.
It knows nothing after it's been created in your code.
This may get you a bit closer and might shed some light on how
inheritance works:
MAIN2.CFC
<cfcomponent displayname="main2" output="false">
<cffunction name="init" access="public" output="false" returntype="main2">
<cfargument name="dsn" type="string" required="true" />
<cfset setDsn(arguments.dsn) />
<cfreturn this />
</cffunction>
<cffunction name="getDsn" access="public" output="false" returntype="string">
<cfreturn variables.dsn />
</cffunction>
<cffunction name="setDsn" access="public" output="false" returntype="void">
<cfargument name="dsn" type="string" required="true" />
<cfset variables.dsn = arguments.dsn />
</cffunction>
</cfcomponent>
CHILD2.CFC
<cfcomponent displayname="child2" output="false" extends="main2">
<cffunction name="init" access="public" output="false" returntype="child2">
<cfargument name="dsn" type="string" required="true" />
<cfset setDsn(arguments.dsn) />
<cfreturn this />
</cffunction>
</cfcomponent>
TEST.CFM
<cfscript>
main = CreateObject("component", "main2").init("MyMainDsn");
child = CreateObject("component", "child2").init("MyChildDSN");
</cfscript>
<cfoutput>
child.dsn: #child.getDsn()#<br />
main.dsn: #main.getDsn()#
</cfoutput>
There are a bunch of different ways to do this, but the gist of this
simple example is to show how inheritance works in a bit more detail.
Unless you set the value of dsn in your child object somehow, it's not
going to exist regardless of whether you create it inside your parent
object (which I still question) or as a separate object as I'm doing
above. In this case I decided to put a get and set method for the dsn
in the parent object, and as you can see those methods are inherited by
the child (see the call to setDsn() in the child init() method), but
you still have to set the variable in child because it's a separate
object. You don't, however, have to declare these methods in the child
object.
Also, I'm using the variables scope because that way you protect your
variables better. Personally I never use the this scope, I always use
the variables scope and provide get and set methods to the variables I
want publicly accessible.
I hope that helps a bit--I'd also suggest reading some general OO
books/materials to get a better sense of how inheritance works. There
are more clear examples than what I've done above but I wanted to keep
things in the context of what you were trying to do.
Let me know if any of this needs clarification.
Matt
--
Matt Woodward
[email]mpwoodward@gmail.com[/email]
Team Macromedia - ColdFusion
mpwoodward *TMM* Guest
-
bhalper #3
Re: CFC extends
Thanks, that makes perfect sense.....
basically what you are saying is that although methods may be availbale to the
child cfc through inheritance the value set within them may not. This is basis
of my confusion and in al my research i have never been able to find thi sout
for sure......thank you.
So......as i am already passing the value of my DSN in each CFC as it loads,
it would seem there is liitle benefit/reason to use inheritance in this way.
bhalper Guest
-
mpwoodward *TMM* #4
Re: CFC extends
On 2005-07-16 09:41:18 -0500, "bhalper" <webforumsuser@macromedia.com> said:
Exactly--setting a value for a variable in the parent does not> Thanks, that makes perfect sense.....
> basically what you are saying is that although methods may be
> availbale to the child cfc through inheritance the value set within
> them may not. This is basis of my confusion and in al my research i
> have never been able to find thi sout for sure......thank you.
automatically make that specific value available in the child.
That might be the case here--I used the get/set methods to illustrate> So......as i am already passing the value of my DSN in each CFC as it
> loads, it would seem there is liitle benefit/reason to use inheritance
> in this way.
how it *might* make sense to use inheritance, but just for the dsn it
may not make sense since your goal was to not have to set it, which
you'll have to do.
Matt
--
Matt Woodward
[email]mpwoodward@gmail.com[/email]
Team Macromedia - ColdFusion
mpwoodward *TMM* Guest
-
bhalper #5
Re: CFC extends
I have heard from VB and JAVA programmers that CFCs are not TRUE objects and
when i ask why they maintain that inhertiance is key factor. I have read and
have been told that in VB for instance if one set instance data in a parent
class that value will be passed to the child. So if one set a class called car
and the instance name of the car is 'Aston martin' the child class 'wheels'
will be able to maintain that it the wheels of an Aston Martin.
As you pointed perhaps i have misunderstood inhertinacfe or have i uncovered
the reason it has been claimed that cfc are not true objects?
bhalper Guest
-
mpwoodward *TMM* #6
Re: CFC extends
On 2005-07-16 10:09:56 -0500, "bhalper" <webforumsuser@macromedia.com> said:
Nope, nope, nope. Doesn't work this way. I'll address in more detail> I have heard from VB and JAVA programmers that CFCs are not TRUE
> objects and when i ask why they maintain that inhertiance is key
> factor. I have read and have been told that in VB for instance if one
> set instance data in a parent class that value will be passed to the
> child. So if one set a class called car and the instance name of the
> car is 'Aston martin' the child class 'wheels' will be able to maintain
> that it the wheels of an Aston Martin.
below. Either VB works completely differently than all other languages
or you're talking about something other than inheritance here.
There are lots of arguments as to how OO CF really is, but inheritance> As you pointed perhaps i have misunderstood inhertinacfe or have i
> uncovered the reason it has been claimed that cfc are not true objects?
isn't one of the issues where CF behaves differently from any other OO
language, so I'm not sure what the VB and Java programmers you've
talked to are talking about. You'd have to get more details for me to
address exactly what they're saying. Now in CF 6.0 there was no
ability to call "super" so that affected some things, but that was
added in 6.1 so now inheritance in CF behaves for the most part like it
does in any other language. If you have more details on this argument
you've heard post them--I'd be curious to see what they were talking
about.
As for your example of settings instance data that gets passed to the
child in VB, I'd be VERY surprised if this is true. I don't know any
VB at all (when I do .NET I use C#), but if VB does that then it's VB
that's breaking typically OO rules of inheritance, not CF, and I can
tell you for a fact that it doesn't work that way in Java.
Think about it this way. Inheritance has NOTHING WHATSOEVER to do with
specific object instances. Inheritance has to do with what in Java
terms are CLASSES, or generic, uninstantiated objects. Inheritance
allows you to inherit the methods and attributes of the parent object
*as a blueprint*, not as specific values. Why the heck would you WANT
all your child objects to inherit the specific variables of a
particular instance of a parent object? That would be extremely
limiting. Child objects inherit things from the parent object, but
they are not tied to the values of any particular instance of the
parent object. Hope that makes sense.
I'd suggest getting a good Java or OO book and reading up on this if
you want to learn more, and if you have specific details about what the
VB and Java people you spoke with were talking about I'd be curious to
hear them. My initial reaction is that they were talking about
something other than inheritance, because this simply is not the way
inheritance works in any OO language.
Matt
--
Matt Woodward
[email]mpwoodward@gmail.com[/email]
Team Macromedia - ColdFusion
mpwoodward *TMM* Guest
-
bhalper #7
Re: CFC extends
thanks matt
In answer to your question
'Why the heck would you WANT
all your child objects to inherit the specific variables of a
particular instance of a parent object? '
I can think of one reason, say you have parent object that is isntatitated in
the session scope, so it's inatsnce data is for a specfic person and there is
a child object that is also has a session intanse wouldn't one want all the
instance values passed from the parent to child. Just as in my app, the cfc's
application instance (the dsn and other app specfic values ) could be extended
to the children.
If this is not inheritance than what is it?
bhalper Guest
-
mpwoodward *TMM* #8
Re: CFC extends
On 2005-07-17 03:26:10 -0500, "bhalper" <webforumsuser@macromedia.com> said:
Well, it's not inheritance. You're still thinking of inheritance as> thanks matt
> In answer to your question 'Why the heck would you WANT all your
> child objects to inherit the specific variables of a particular
> instance of a parent object? '
> I can think of one reason, say you have parent object that is
> isntatitated in the session scope, so it's inatsnce data is for a
> specfic person and there is a child object that is also has a session
> intanse wouldn't one want all the instance values passed from the
> parent to child. Just as in my app, the cfc's application instance (the
> dsn and other app specfic values ) could be extended to the children.
> If this is not inheritance than what is it?
data-related as opposed to generic method- and attribute-related. The
fact that all these objects have a generic DSN property and methods for
getting and setting the DSN, that's inheritance. The specific values
that these get set to have nothing to do with inheritance. What you're
talking about is just specific data and in my opinion you wouldn't even
necessarily use inheritance for this sort of thing. I suppose you
could have a generic base DataObject class that has a DSN property and
methods related to DSN, but if you extend that base class into other
data object-type classes, you'd still have to set the DSN for each one.
No way around that--inheritance has nothing to do with specific
instances of objects.
One way to do what you're asking about: Set the app-specific stuff in a
single object, put it in the application scope, and then every other
object that needs the DSN just gets it from the object that holds all
this data. This is part of instantiating any object, inheritance or
not--you have to set the values for the attributes in the object.
Again, specific attribute values have nothing to do with inheritance.
Don't think about inheritance as it relates to specific data values.
(Yes, I know I'm repeating myself.) Think about inheritance as a way
of taking a blueprint for one object and extending it (hence the
keyword "extends") by adding functionality to the child class. One of
the classic examples is a car. I'll keep this very simple and limited
in terms of the number of attributes but hopefully this will help you
get the gist of it. Let's say you have a Car object that has all the
attributes and methods associated with a basic Car (I'm limiting mine
to number of doors and color). A Hybrid vehicle is a car, but it has
additional equipment in it since it's partially electric, so you can
extend the basic car and inherit all the generic methods and attributes
of a car (number of doors, color, and so on) and just add the
additional attributes and methods associated with a hybrid vehicle (I'm
just using battery charge percent here).
CAR.CFC
<cfcomponent displayname="Car" output="false">
<cffunction name="init" access="public" output="false" returntype="Car">
<cfargument name="numberOfDoors" type="numeric" required="false"
default="0" />
<cfargument name="color" type="string" required="false" default="" />
<cfscript>
setNumberOfDoors(arguments.numberOfDoors);
setColor(arguments.color);
</cfscript>
<cfreturn this />
</cffunction>
<cffunction name="getNumberOfDoors" access="public" output="false"
returntype="numeric">
<cfreturn variables.numberOfDoors />
</cffunction>
<cffunction name="setNumberOfDoors" access="public" output="false"
returntype="void">
<cfargument name="numberOfDoors" type="numeric" required="true" />
<cfset variables.numberOfDoors = arguments.numberOfDoors />
</cffunction>
<cffunction name="getColor" access="public" output="false"
returntype="string">
<cfreturn variables.color />
</cffunction>
<cffunction name="setColor" access="public" output="false" returntype="void">
<cfargument name="color" type="string" required="true" />
<cfset variables.color = arguments.color />
</cffunction>
</cfcomponent>
HYBRID.CFC
<cfcomponent displayname="Hybrid" output="false" extends="Car">
<cffunction name="init" access="public" output="false" returntype="Hybrid">
<cfargument name="numberOfDoors" type="numeric" required="false"
default="0" />
<cfargument name="color" type="string" required="false" default="" />
<cfargument name="batteryChargePercent" type="numeric"
required="false" default="0" />
<cfscript>
setNumberOfDoors(arguments.numberOfDoors);
setColor(arguments.color);
setBatteryChargePercent(arguments.batteryChargePer cent);
</cfscript>
<cfreturn this />
</cffunction>
<cffunction name="getBatteryChargePercent" access="public"
output="false" returntype="numeric">
<cfreturn variables.batteryChargePercent />
</cffunction>
<cffunction name="setBatteryChargePercent" access="public"
output="false" returntype="void">
<cfargument name="batteryChargePercent" type="numeric" required="true" />
<cfset variables.batteryChargePercent = arguments.batteryChargePercent />
</cffunction>
</cfcomponent>
TESTCARS.CFM
<cfscript>
car = CreateObject("component", "Car").init(4, "Red");
hybrid = CreateObject("component", "Hybrid").init(2, "Green", 100);
</cfscript>
<cfoutput>
<h3>Car</h3>
<ul>
<li>Number of Doors: #car.getNumberOfDoors()#</li>
<li>Color: #car.getColor()#</li>
</ul>
<h3>Hybrid</h3>
<ul>
<li>Number of Doors: #hybrid.getNumberOfDoors()#</li>
<li>Color: #hybrid.getColor()#</li>
<li>Battery Charge Percent: #hybrid.getBatteryChargePercent()#%</li>
</ul>
</cfoutput>
Notice that even though I don't have the methods related to color and
number of doors in my Hybrid class, I can still use those methods
because I inherit them from the Car class. Note also however that the
specific instances are completely independent of one another, as they
should be. Even if the number of doors and color of my hybrid are the
same as my regular car, I have to set those for the hybrid *because
it's an independent object*.
I hope that helps--I'd really suggest reading up on this in a good OOP
or Java book because that will probably help you understand it more
than what I'm explaining here. Or just google--you'll find tons of
information about this.
Matt
--
Matt Woodward
[email]mpwoodward@gmail.com[/email]
Team Macromedia - ColdFusion
mpwoodward *TMM* Guest
-
bhalper #9
Re: CFC extends
That's makes perfect sense. It seems as if I haveconfused inhertiance with
instance data
Your examaple makes sense as well. I will speak to my VB guys and find out
what they are taking about.
Either i have misunderstood them of they were talking rubbish (which given the
nature of their chosen language) is not exactly out of the realms of
possiblility... ;)
bhalper Guest
-
mpwoodward *TMM* #10
Re: CFC extends
On 2005-07-17 09:57:03 -0500, "bhalper" <webforumsuser@macromedia.com> said:
Heh--always a possibility ... although VB .NET is pretty OO from what I> That's makes perfect sense. It seems as if I haveconfused inhertiance
> with instance data
>
> Your examaple makes sense as well. I will speak to my VB guys and find
> out what they are taking about.
> Either i have misunderstood them of they were talking rubbish (which
> given the nature of their chosen language) is not exactly out of the
> realms of possiblility... ;)
understand, so I'd be curious to know what they meant as well. I do
know that C# works just like any other OO language from the standpoint
of inheritance, so unless there's some specific feature of VB that
behaves differently, I'm not sure what they would have been referring
to.
Glad this helped clarify things.
Matt
--
Matt Woodward
[email]mpwoodward@gmail.com[/email]
Team Macromedia - ColdFusion
mpwoodward *TMM* Guest
-
shirai #11
Re: CFC extends
Of course I haven't looked in the forums for ages but I *have* to reply to the
first thread I look at. Such is the draw of community. :)
First of all, I wanted to say to mpwoodward that the content of your posts is
informative and kudos for you to take the time to explain OO to bhalper in such
detail. It's always nice to see long informative posts.
Second, I just wanted to note to bhalper that while inheritance isn't the
answer to your problems, there certainly is a solution.
What you could do it simply call a function inside the child to set the values
from the parent object. Sorry, my CFC is very rusty right now as I've been
avoiding CFC's for performance reasons (1ms instantiation overhead). At any
rate, there probably is a *cleaner* answer than below but you should be able to
get the point:
*** parent ***
<cfcomponent>
<cffunction name="setdsn">
<cfargument name="dsn">
<cfset this.dsn=arguments.dsn>
</cffunction>
</cfcomponent>
*** Child ***
<cfcomponent>
<cffunction name="init">
<cfargument name="parent">
<cfset this.dsn=arguments.parent.dsn>
</cffunction>
<cffunction name="getdsn">
<cfreturn this.dsn>
</cffunction>
</cfcomponent>
<cfscript>
parent=createobject("component","components.parent ").setDSN("myDSN");
child=createobject("component","components.child") .init(parent);
writeoutput(child.getDSN());
</cfscript>
Note that you are passing the PARENT INSTANCE to the child constructor which
in turn gets placed into the CHILD INSTANCE.
Obviously, mpwoodward's method is superior if you ONLY have to grab the DSN
from the parent. You may as well just set it as a string. But I think you
probably are thinking of setting many properties in the parent CFC. In this
case, you could (and should) pass the entire object instance and then regrab
the data from it.
If you always to grab ALL the properties, you should be able to cfloop through
the properties in the parent and copy them all to the child. Haven't tried it
but this=arguments.parent MIGHT work (but I have my doubts).
Anyways, either of these would give you very script-like efficiencies in
coding at the cost of performance and perhaps, potentially, some debugging
issues (since you have to look up the chain to see what this variables get set).
Sunny
p.s. please forgive any errors. Didn't check any code and, as I said, have
abstained from CFCs for a while. In case you're wondering, I've just been using
functions with structured naming to simulate CFCs. cfincludes run about 63x
faster (actually timed it) and functions execute 60% faster than component
methods. Not to scare you away. Probably only matters in REALLY performance
intensive applications.
shirai Guest
-



Reply With Quote

