组件上 accessors=true 的意外行为
Unexpected behaviour with accessors=true on a component
我正在尝试在 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 定义修改为 not set accessors to true,则转储显示如下:
所以没有合成访问器(正如预期的那样),而且现在甚至没有显示属性(无论是否具有变量范围的值)。
我真的不明白 "properties" 和访问器设置的这种混淆?当然访问器设置应该只影响那些访问器方法是否被创建?
如果我只在其中一个平台上看到这个,我可能会把它归结为 writeDump()
如何解释 属性 定义。但是 ColdFusion 11 上的行为是相同的,所以看起来确实存在一些我不太了解的行为差异。
谁能解释一下?有没有解释它的文档?如果不是...嗯...为什么不呢?
我的基本担心是 属性 值没有被存储 "properly",一旦我实现更多代码可能会给我带来问题。
更新:
至少在 ColdFusion 上,这似乎只是 writeDump()
行为的一个变化,因为如果属性有吸气剂(无论是否设置了 accessors
标志),那么 属性 值开始出现在转储中。不过 Lucee 的情况并非如此,所以这里仍然有一个问号。
为了全面披露,这个问题是我在我的博客 ("CFML: trying to understand accessors") 上也提出的一个问题的摘要。重复是故意的,因为我的博客与本网站的受众不同。
没有 accessors=true
,property
声明只是元数据。
对于 accessors=true
,property
声明会触发 getter/setter 的生成,因此 property
既是 variables
范围项 又一对方法。
在您的构造函数中,您分配给 variables
范围项——这与使用生成的 setter 相同——当 CFML 转储组件时,它会看到 property
元数据和生成的 getter,因此它显示这些属性具有的值(因为它可以轻松安全地调用生成的 getter)。
ACF9 就这样诞生了。在那之前,属性 文档中的定义是正确的:cf属性 声明 只是元数据 。 (参见转储(getMetaData())。
在 ACF9 中,这不再完全正确,原因有 3 个:
使用 accessors=true
为每个 属性 生成一个 getter 和 setter 并且这些访问器读取和写入 变量范围。 Cf属性 不再只是元数据,而是对实例的行为有直接影响。我喜欢将其视为真正的 OO 属性(偶然引入)的 CF 版本。
cfdump 实现根据 属性 声明更改其行为。如果定义了 property name;
并且方法 getName()
存在(生成或实现)它被添加到转储的 属性 部分。
属性 属性控制 ORM。
自从我了解了这些功能后,我将所有 (public) 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 总是从转储中调用 getters,而在 Railo/Lucee 中显示变量范围的值。因此,上述示例(
getDebug()
和 getName()
)不适用于 Railo/Lucee。
- 如果 getter 不是 public 或导致错误,转储显示 属性 的空字符串(此处不确定,可能是 属性相反)。
- 属性 扩展 CFC 中的声明将被忽略。这让我在使用继承的 ORM 实体中有些头疼,因为你不允许声明一个 属性 两次。因此,您无法显示在基本 CFC 中定义的 属性。
- Railo/Lucee 似乎忽略了 属性 类型。所有访问器只接受 return 字符串(请参阅 getMetaData())。
- 轻微:在 ACF 中,当您激活访问器时,但为 属性 停用 getter 和 setter:
property name="user" getter="false" setter="false";
它在转储中仍然可见 - 它应该隐藏起来。
我正在尝试在 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 定义修改为 not set accessors to true,则转储显示如下:
所以没有合成访问器(正如预期的那样),而且现在甚至没有显示属性(无论是否具有变量范围的值)。
我真的不明白 "properties" 和访问器设置的这种混淆?当然访问器设置应该只影响那些访问器方法是否被创建?
如果我只在其中一个平台上看到这个,我可能会把它归结为 writeDump()
如何解释 属性 定义。但是 ColdFusion 11 上的行为是相同的,所以看起来确实存在一些我不太了解的行为差异。
谁能解释一下?有没有解释它的文档?如果不是...嗯...为什么不呢?
我的基本担心是 属性 值没有被存储 "properly",一旦我实现更多代码可能会给我带来问题。
更新:
至少在 ColdFusion 上,这似乎只是 writeDump()
行为的一个变化,因为如果属性有吸气剂(无论是否设置了 accessors
标志),那么 属性 值开始出现在转储中。不过 Lucee 的情况并非如此,所以这里仍然有一个问号。
为了全面披露,这个问题是我在我的博客 ("CFML: trying to understand accessors") 上也提出的一个问题的摘要。重复是故意的,因为我的博客与本网站的受众不同。
没有 accessors=true
,property
声明只是元数据。
对于 accessors=true
,property
声明会触发 getter/setter 的生成,因此 property
既是 variables
范围项 又一对方法。
在您的构造函数中,您分配给 variables
范围项——这与使用生成的 setter 相同——当 CFML 转储组件时,它会看到 property
元数据和生成的 getter,因此它显示这些属性具有的值(因为它可以轻松安全地调用生成的 getter)。
ACF9 就这样诞生了。在那之前,属性 文档中的定义是正确的:cf属性 声明 只是元数据 。 (参见转储(getMetaData())。
在 ACF9 中,这不再完全正确,原因有 3 个:
使用
accessors=true
为每个 属性 生成一个 getter 和 setter 并且这些访问器读取和写入 变量范围。 Cf属性 不再只是元数据,而是对实例的行为有直接影响。我喜欢将其视为真正的 OO 属性(偶然引入)的 CF 版本。cfdump 实现根据 属性 声明更改其行为。如果定义了
property name;
并且方法getName()
存在(生成或实现)它被添加到转储的 属性 部分。属性 属性控制 ORM。
自从我了解了这些功能后,我将所有 (public) 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 总是从转储中调用 getters,而在 Railo/Lucee 中显示变量范围的值。因此,上述示例(
getDebug()
和getName()
)不适用于 Railo/Lucee。 - 如果 getter 不是 public 或导致错误,转储显示 属性 的空字符串(此处不确定,可能是 属性相反)。
- 属性 扩展 CFC 中的声明将被忽略。这让我在使用继承的 ORM 实体中有些头疼,因为你不允许声明一个 属性 两次。因此,您无法显示在基本 CFC 中定义的 属性。
- Railo/Lucee 似乎忽略了 属性 类型。所有访问器只接受 return 字符串(请参阅 getMetaData())。
- 轻微:在 ACF 中,当您激活访问器时,但为 属性 停用 getter 和 setter:
property name="user" getter="false" setter="false";
它在转储中仍然可见 - 它应该隐藏起来。