Ask a Question related to Coldfusion - Advanced Techniques, Design and Development.

  1. #1

    Default 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

  2. Similar Questions and Discussions

    1. 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 { }
    2. 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...
    3. 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...
    4. 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:...
    5. [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...
  3. #2

    Default 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

  4. #3

    Default 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

  5. #4

    Default Re: CFC extends

    On 2005-07-16 09:41:18 -0500, "bhalper" <webforumsuser@macromedia.com> said:
    > 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.
    Exactly--setting a value for a variable in the parent does not
    automatically make that specific value available in the child.
    > 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.
    That might be the case here--I used the get/set methods to illustrate
    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

  6. #5

    Default 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

  7. #6

    Default Re: CFC extends

    On 2005-07-16 10:09:56 -0500, "bhalper" <webforumsuser@macromedia.com> said:
    > 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.
    Nope, nope, nope. Doesn't work this way. I'll address in more detail
    below. Either VB works completely differently than all other languages
    or you're talking about something other than inheritance here.
    > As you pointed perhaps i have misunderstood inhertinacfe or have i
    > uncovered the reason it has been claimed that cfc are not true objects?
    There are lots of arguments as to how OO CF really is, but inheritance
    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

  8. #7

    Default 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

  9. #8

    Default Re: CFC extends

    On 2005-07-17 03:26:10 -0500, "bhalper" <webforumsuser@macromedia.com> said:
    > 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?
    Well, it's not inheritance. You're still thinking of inheritance as
    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

  10. #9

    Default 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

  11. #10

    Default Re: CFC extends

    On 2005-07-17 09:57:03 -0500, "bhalper" <webforumsuser@macromedia.com> said:
    > 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... ;)
    Heh--always a possibility ... although VB .NET is pretty OO from what I
    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

  12. #11

    Default 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

  13. #12

    Default Re: CFC extends

    kudos? are you into wulfram?
    p_regius
    Stefan K. Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139