Coldfusion 组件上访问器的意外行为=true

Coldfusion 组件上访问器的意外行为=true,coldfusion,cfml,lucee,Coldfusion,Cfml,Lucee,我试图在Lucee上的组件上使用综合访问器(尽管这个问题在ColdFusion上似乎也一样) 复制代码: // Person.cfc component accessors=true { property firstName; property lastName; function init(firstName, lastName){ variables.firstName = arguments.firstName; variable

我试图在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的情况并非如此,因此仍然存在一个问号


为了充分披露,这个问题是我在我的博客(“”)上提出的一个问题的总结。复制是故意的,因为我的博客与本网站的读者不同。

如果没有
accessors=true
,那么
属性声明就只是元数据

使用
accessors=true
属性
声明触发getter/setter的生成,因此
属性
既是
变量
范围项又是一对方法


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

这是ACF9提出的。在此之前,属性文档中的定义是正确的:cfproperty声明是元数据(请参阅dump(getMetaData())

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

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

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

  • 属性属性控制ORM

  • 因为我了解了这些特性,所以我设计了所有(公共)CFC,使其在转储时看起来正确,例如,我只在希望其可见时使用属性声明(+getter)。此外,您可以实现仅由转储调用的方法,并且在实例化时不花费任何成本:

    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”;
      它在转储中仍然可见-应该隐藏它

    是的,这是def的外观(请参阅我的更新)。Lucee的行为与ColdFusion的行为略有不同。我猜Lucee查找设置和方法;CF只查找方法。区别完全在于转储行为,而不是其他。这只是CF9构造函数行为的一个例子吗?在CF9中,init()成为一个真正的构造函数,如果你有一个,它会在你使用new关键字时被自动调用,就像在Java中一样。如果你将init()重命名为Person(),同样的事情也会发生。如果你是正确的,那么如果你使用了其他函数名,它也会发生,但实际上没有。只有当CF作为构造函数运行时才会发生这种情况。