1

我有两个 CFC,它们是具有 DAO 功能的 Bean。我已经在子 cfc 扩展父的地方设置了继承。

两个对象具有相同的结构;函数:init、read 等和 Properties:ID 等。

当我创建子对象时,我传递了一个 ID,它读取数据,获取父对象的外键 parentID,然后使用适当的参数调用 Super.init()。

我出乎意料的结果是:child 和 parentID 的 ID 相同,并且是返回对象时的 parentID 值。childs variables.ID 在 super 调用后被覆盖。我假设两者都可以访问变量范围,因此当父级设置 variables.ID 时,它会覆盖子 variables.ID。如果不以不同的方式命名 ID,是否可以避免这种情况?

父对象的读取函数似乎没有执行。例如,如果我重命名父母读取函数“read2”,该函数就会执行。我还怀疑这些函数位于共享范围内,因此正在执行子读取函数。

有什么方法可以保持相同的 cfc 结构并使此功能按预期工作?

提前致谢。

<cfcomponent accessors="true" extends="Custom" output="false">
<cfproperty name="ID" type="numeric" />
<cfproperty name="listID" type="numeric" />
<cfproperty name="customfieldID" type="numeric" />
<cfscript>
    variables.dsn = '';
</cfscript>

<cffunction name="init" access="public" output="false" returntype="ListCustom">
    <cfargument name="dsn" type="string" required="true" />
    <cfargument name="ID" type="numeric" required="true" />
    <cfargument name="listID" type="numeric" required="false" default="0" />
    <cfargument name="customFieldID" type="numeric" required="false" default="0" />
    <cfscript>
        variables.dsn = arguments.dsn;
        variables.ID = arguments.ID;
        variables.listID = arguments.listID;
        variables.customFieldID = arguments.customFieldID;
        if (variables.ID){
            read();
            if (variables.customFieldID){
                Super.init(dsn=variables.dsn,ID=variables.customfieldID);
            }
        }
    </cfscript>
    <cfreturn this />
</cffunction>

<cffunction name="read" access="private" output="false" returntype="void">
    <cfquery name="local.q" datasource="#variables.dsn#">
        SELECT customfieldID, listID
        FROM listCustomFields
        WHERE ID = <cfqueryparam value="#variables.ID#" cfsqltype="cf_sql_integer">
    </cfquery>
    <cfif local.q.recordcount>
        <cfset variables.listID = local.q.listID />
        <cfset variables.customFieldID = local.q.customFieldID />
    </cfif>
</cffunction>

<cfcomponent accessors="true" output="false">

<cfproperty name="ID" type="numeric" />
<cfproperty name="fieldName" type="string" />

<cfscript>
    variables.dsn = '';
</cfscript>

<cffunction name="init" access="public" output="false" returntype="Custom">
    <cfargument name="dsn" type="string" required="true" />
    <cfargument name="ID" type="numeric" required="true" />
    <cfargument name="fieldName" type="string" required="false" default="" />
    <cfscript>
        variables.dsn = arguments.dsn;
        variables.ID = arguments.ID;
        variables.fieldName = arguments.fieldName;
        if (variables.ID){
            read();
        }
    </cfscript>
    <cfreturn this />
</cffunction>

<cffunction name="read" access="private" output="false" returntype="void">
    <cfquery name="local.q" datasource="#variables.dsn#">
        SELECT fieldName
        FROM CustomField
        WHERE ID = <cfqueryparam value="#variables.ID#" cfsqltype="cf_sql_integer">
    </cfquery>
    <cfif local.q.recordcount>
        <cfset variables.fieldName = local.q.fieldName />
    </cfif>
</cffunction>

4

3 回答 3

2

由于您正在扩展对象,因此父级和子级的变量范围是共享的,因此variables.id在父级中的变量范围在子级中是相同variables.id的,并且子级和父级都可以访问或覆盖存储在那里的内容。

同样使用扩展父函数read将永远不会被调用,除非子函数读取显式调用它super.read()

此外,除非您已将应用程序和组件设置为使用 ORM,否则这些cfproperty标签仅适用于 Web 服务。

于 2012-10-09T17:05:46.110 回答
1

首先,garygilbert 和 KRC 都帮助我指出了正确的方向。谢谢你。

我收集了以下信息:孩子和父母都将共享相同的变量范围,因此在为 super 中的 variables.ID 分配值时,子 variables.ID 值被覆盖。

同样,由于 OO 函数覆盖,子函数 read 优先于父 read 函数。

我调整后的解决方案:在调用 Super 函数之前设置一个临时 ID,即子 ID。因为如果我将 ID 传递给 init 函数,读取函数会自动调用,我想避免在父对象中执行此操作,因为它仍会调用子读取。我调用 Super.init(dsn) 进行初始化,然后调用 Super.setID(ID),最后调用 Super.read()。超级调用后,我恢复了最初的孩子ID。

        <cfscript>
        variables.dsn = arguments.dsn;
        variables.ID = arguments.ID;
        variables.listID = arguments.listID;
        variables.customFieldID = arguments.customFieldID;
        if (variables.ID){
            read();
            if (variables.customFieldID){
                variables.tempID = variables.ID;
                Super.init(dsn=variables.dsn);
                Super.setID(variables.customfieldID);
                Super.read();
                variables.ID = variables.tempID;
            }
        }
    </cfscript>
于 2012-10-09T19:17:56.757 回答
0

我认为发生这种情况的原因是因为 CF 如何cfproperty在整个对象的 VARIABLES 范围内而不是在 CFC 的专有范围内限定值(如普遍接受的 VARIABLES.instance 结构实践)。

VARIABLES 范围在您的对象之间共享,包括它是继承的父对象,因此通过在父对象和子对象中命名 ID 值,您实际上只是声明了两次,而不是声明了两个单独的变量。然后,当您将 ID 传递给 yoursuper.init()时,它会将您的 ID 值覆盖到您的子 ID 到您传递给父 bean 的 ID 值,从而导致您的结果。如果您想以不同的方式看到这一点,请尝试在您的孩子中创建一个测试函数,该函数与您的父母中的变量名称共享。在您的 中为该变量分配一个值super.init(),然后观察您的子函数从您的对象中消失。

所以回答,我不认为你可以不做一些你不想做的事情来解决这个问题。您需要为父 ID 使用不同的名称,或者不使用内置访问器功能并手动编写所有 getter 函数,将它们设置在 CFC 专有的范围内。

于 2012-10-09T15:43:37.513 回答