2012-10-09 38 views
1

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

两个物体具有相同的结构;函数:初始化,读取等等和属性:ID等

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

我意外的结果是: 子对象的ID和parentID都是相同的,并且是返回对象时的parentID值。超级调用后,孩子的变量.ID被覆盖。我假设变量作用域可以被两者访问,所以当父设置变量.ID时,它会覆盖子变量.ID。如果没有对ID进行不同的命名,这可以避免吗

父对象的读取功能似乎不会执行。例如,如果我重命名父节点读取函数'read2',则该函数执行。我也怀疑这些函数驻留在一个共享范围内,因此childs读取函数正在执行。

是否有任何方法来维护相同的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> 

+3

你能分享一些代码吗?另外,在父母/子女关系中,我不确定是否有孩子延长父母的路要走。两者都可以扩展一个“基础”对象,但是不确定孩子是否延伸父母是一条路。 –

回答

1

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

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

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

我调整后的解决方案: 设置一个临时ID,它是调用超级函数之前的子ID。 因为如果我将ID传递给init函数,read函数会自动调用,所以我想避免在父对象中这样做,因为它仍然会调用子读取。我调用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> 
0

我想,为什么发生这种情况的原因是因为CF如何在整个对象的变量的作用域,而不是在独家范围作用域cfproperty值CFC(像普遍接受的VARIABLES.instance结构实践)。

VARIABLES作用域在对象之间共享,包括它的继承父对象,所以通过在父对象和子对象中命名ID值,实际上只是声明它两次,而不是声明两个单独的变量。然后,当您将ID传递给您的super.init()时,它会将您的ID值覆盖到您的子ID,并将其传递给父bean中的ID值,从而产生结果。如果您希望以不同的方式看到此操作,请尝试在您的孩子中创建一个测试函数,该函数在您的父级中共享变量的名称。在您的super.init()中为该变量赋值,并观察您的子函数从您的对象中消失。

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

+0

我明白了一半;当你说读取函数没有执行时我假设你指的是你父母的init函数调用它自己的读取。正如加里所说,这个电话必须用超级电话才能完成。 –

+1

:这两个cfc都有init和read函数。我在“答案”中提供了最终细节。谢谢! – David

2

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

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

另外,除非您已设置应用程序和组件以使用ORM,否则cfproperty标记仅适用于Web服务。

+1

@garygilbert:谢谢你的回应。我将指出“仅适用于web服务”不再适用于CF服务器的版本9+。当组件属性访问器设置为true时,使用cfproperty将为cfproperties创建'虚拟'getter和setter。 – David

+0

@大卫,我忘记了CF9中引入的隐式setter和getter – garyrgilbert