11

我正在尝试在 Lucee 上的组件上使用合成访问器(尽管这个问题在 ColdFusion 上似乎也一样)。

复制代码:

// Person.cfc
component accessors=true {

    property firstName;
    property lastName;

    function init(firstName, lastName){
        variables.firstName = arguments.firstName;
        variables.lastName = arguments.lastName;
    }

}

和调用代码:

// person.cfm
person = new Person("Abigail", "Bowen");
writeDump(person);

请注意我在这里没有使用合成访问器,我只是将参数值设置为同名变量范围的变量。

但是,当我运行此代码时,我看到了:

转储输出显示属性

请注意如何填充属性。这没有问题,但我显然不明白该accessors标志应该如何工作。我认为它只是为了为我(它有)综合一些访问器方法,但仅此而已。

另请注意,如果我修改 CFC 定义以将访问器设置为 true,则转储会显示以下内容:

没有属性的转储

因此没有合成访问器(如预期的那样),而且现在甚至没有显示属性(是否具有变量范围的值)。

我真的不明白“属性”和访问器设置的这种混淆?当然访问器设置应该只影响这些访问器方法是否被创建?

如果我只在其中一个平台上看到这个,我可能会把它归结为如何writeDump()解释属性定义的变幻莫测。但是在 ColdFusion 11 上的行为是相同的,所以看起来我不太明白的行为确实存在一些差异。

谁能解释一下?有没有解释它的文档?如果不是……嗯……为什么不呢?

我在这里的潜在担忧是,属性值没有“正确”存储,一旦我实现更多代码,可能会给我带来问题。

更新:至少在 ColdFusion 上,这似乎只是writeDump()' 行为的改变,因为如果属性有 getter(无论是否accessors设置了标志),那么属性值就会开始出现在转储中。不过,Lucee 的情况并非如此,所以那里仍然有一个问号。

为了充分披露,这个问题是我在我的博客上提出的一个问题的总结(“ CFML:试图理解访问器”)。重复是故意的,因为我的博客与本网站的受众不同。

4

2 回答 2

11

没有accessors=trueproperty声明只是元数据。

使用accessors=trueproperty声明会触发 getter / setter 的生成,因此 aproperty既是variables范围项是一对方法。

在您的构造函数中,您分配给variables范围项——这与使用生成的 setter 相同——并且当 CFML 转储组件时,它会看到property元数据和生成的 getter,因此它会显示这些属性具有的值(因为它可以轻松安全地调用生成的getter)。

于 2015-02-26T02:20:56.140 回答
2

这提出了ACF9。在那之前,属性文档中的定义是正确的:cfproperty 声明只是元数据。(见转储(getMetaData())。

在 ACF9 中,这不再完全正确,原因有 3 个:

  1. 为每个属性生成一个 getter 和 setter ,accessors=true这些访问器读取和写入变量 scope。Cfproperty 不再只是元数据,而是直接影响实例的行为。我喜欢将其视为真正 OO 属性的 CF 版本(偶然引入)。

  2. cfdump实现根据属性声明更改其行为。如果property name;已定义且方法getName()存在(生成或实现),则将其添加到转储的属性部分。

  3. 属性属性控制 ORM。

由于我了解了这些功能,因此我将所有(公共)CFC 设计为在倾倒时看起来正确,例如。当我想让它可见时,我只使用属性声明(+ getters)。此外,您可以实现仅由转储调用并且在实例化时不花费任何成本的方法:

struct function getDebug(){
    var x = doSomethingExpensive();
    return { "Foo":f, "Bar":b, "Baz":x };
}

//or for a user iterator
string function getName(){
    return qUsers.name[index];
}

我知道的一些警告:

  • ACF 总是从转储中调用 getter,而在 Railo/Lucee 中显示来自变量范围的值。因此,上述示例 (getDebug()getName()) 不适用于 Railo/Lucee。
  • 如果 getter 不是公共的或导致错误,则转储会显示该属性的空字符串(此处不确定,可能是该属性丢失了)。
  • 扩展 CFC 中的属性声明将被忽略。这让我在使用继承的 ORM 实体中有些头疼,因为不允许您两次声明一个属性。因此,您无法显示在基本 CFC 中定义的属性。
  • Railo/Lucee 似乎忽略了属性类型。所有访问器都只接受并返回字符串(参见 getMetaData())。
  • 次要:在 ACF 中,当您激活访问器但停用属性的 getter 和 setter 时:property name="user" getter="false" setter="false";它在转储中仍然可见 - 它应该被隐藏。
于 2015-02-26T14:09:05.580 回答