如何继承类属性

wel*_*rcs 6 coldfusion inheritance

我有一个CFC正在扩展另一个CFC,我想继承超级CFC的属性.我使用extends属性,但我的子类不继承属性,但它继承了方法.两种氟氯化碳都有accessors="true".我尝试accessors="false"在子类中使用,但这不起作用.我的意思是当我在测试页面中运行集合并转储variables.subclass.getResponse()时,它返回{}而不是带有属性及其值的JSON字符串(下面的预期响应).我真的不想在我的子类中复制属性声明.我在ColdFusion 9和Railo 4.2.1上进行了测试.

实际产量:

{}
Run Code Online (Sandbox Code Playgroud)

预期产量:

{"success":false,"errorCode":"1","successMessage":"","errorDetail":"","statusCode":"200","errors":[],"data":"","requestDurationInMilliseconds":"0","errorMessage":"","statusText":"OK"}
Run Code Online (Sandbox Code Playgroud)

示例代码如下:

superclass.cfc

<cfscript>
component accessors="true" {
    property name="data" type="any" required="false" getter="true";
    property name="errorCode" type="numeric" required="false" getter="true";
    property name="errorDetail" type="any" required="false" getter="true";
    property name="errorMessage" type="string" required="false" getter="true";
    property name="errors" type="array" required="false" getter="true";
    property name="requestDurationInMilliseconds" type="numeric" required="false" getter="true";
    property name="statusCode" type="numeric" required="false" getter="true";
    property name="statusText" type="string" required="false" getter="true";
    property name="success" type="boolean" required="false" getter="true";
    property name="successMessage" type="string" required="false" getter="true";

    this.setData("");
    this.setErrorCode(0);
    this.setErrorDetail("");
    this.setErrorMessage("");
    this.setErrors([]);
    this.setRequestDurationInMilliseconds(0);
    this.setStatusCode(200);
    this.setStatusText("OK");
    this.setSuccess(true);
    this.setSuccessMessage("");

    public superclass function init() {
        return this;
    }

    public function getResponse( string format="json" ) {
        if ( structKeyExists(arguments,"format") and arguments.format is "json" ) {
            return serializeJSON(this); 
        }
        else {
            return this;
        }
    }
}
</cfscript>
Run Code Online (Sandbox Code Playgroud)

subclass.cfc

<cfscript>
component accessors="true" extends="superclass" {
    // property name="data" type="any" required="false" getter="true";
    // property name="errorCode" type="numeric" required="false" getter="true";
    // property name="errorDetail" type="any" required="false" getter="true";
    // property name="errorMessage" type="string" required="false" getter="true";
    // property name="errors" type="array" required="false" getter="true";
    // property name="requestDurationInMilliseconds" type="numeric" required="false" getter="true";
    // property name="statusCode" type="numeric" required="false" getter="true";
    // property name="statusText" type="string" required="false" getter="true";
    // property name="success" type="boolean" required="false" getter="true";
    // property name="successMessage" type="string" required="false" getter="true";
}
</cfscript>
Run Code Online (Sandbox Code Playgroud)

测试页面

<cfscript>
    variables.subclass = new subclass();
    variables.subclass.setSuccess(false);
    variables.subclass.setErrorCode(1);
    writedump(getMetaData(variables.subclass));
    writedump(variables.subclass);
    writedump(variables.subclass.getResponse());
</cfscript>
Run Code Online (Sandbox Code Playgroud)

Twi*_*len 0

文档中:

组件继承允许您将组件方法和属性从一个组件导入到另一组件。继承的组件共享它们从其他组件继承的任何组件方法或属性,并且当您实例化扩展父 CFC 时,ColdFusion 会初始化父 CFC 中的实例数据。

鉴于此,我不明白为什么子类不包含父组件的属性;这对我来说似乎违反直觉。我和您一样,期望序列化包含所有父属性和子属性。所以我用你的例子来玩。

父组件的属性看起来就像Java私有属性,并且不暴露给子组件,只有访问器。由于自动生成的访问器将值存储到 CFML 中的对象变量范围中,因此子访问器可以完全访问父访问器存储的值。

原始代码中的问题源于该serializeJSON()函数的工作原理。SerializeJSON 函数似乎只序列化传递组件的属性。您的子类没有表示父访问器设置的值的属性,因此 serializeJSON 返回{}

在使用您的类结构时,我为 getResponse() 方法想出的解决方法是创建一个自定义方法,以将组件属性及其父级属性公开为结构。我序列化从此方法返回的结构,而不是对象本身(如 Sean 在评论中所建议的那样)。在子组件中,我重写了将子组件的自定义属性附加到父组件属性上的方法。我不确定这个重写方法对于更复杂的数据结构的扩展效果如何。

超类.cfc

component accessors="true" {
    property name="data" type="any";

    public superclass function init() {
        data = "Super Class Value";
        return this;
    }

    public function getResponse( string format="json" ) {
        if ( structKeyExists(arguments,"format") and arguments.format is "json" ) {
            return serializeJSON(getProperties());
        }
        else {
            return getProperties();
        }
    }

    public struct function getProperties(){
        return {
            "data" = data
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

子类.cfc

component accessors="true" extends="superclass" {
    property name="subData" type="any";

    public subClass function init() {
        // Could use super.init() to pull parent defaults
        data = "Sub Class Value";
        Subdata = "Sub property";
        return this;
    }

    public struct function getProperties(){
        local.properties = super.getProperties();
        structappend(local.properties,{
            "subData" = subData
        });
        return local.properties;
    }
}
Run Code Online (Sandbox Code Playgroud)

测试.cfm

<cfoutput>
    <cfset superclass = new superclass()>
    <cfset subclass = new subclass()>
    super class
    <br />
    #serializejson(superclass)# // Has one properties to serialize on
    <br />
    GetResponse with custom function:
    <br />
    #superclass.getResponse()# // Displays one property
    <br /><br />
    sub class
    <br />
    #serializejson(subclass)# // One property to serialize
    <br />
    GetResponse with custom function:
    <br />
    #subclass.getResponse()# // Two properties serialized
</cfoutput>
Run Code Online (Sandbox Code Playgroud)