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フラグがどのように機能するかを明確に理解していません。私はそれが私のためにいくつかのアクセサメソッドを合成することを意図しているだけだと思っていました(それは持っています)が、それだけです。

また、アクセサーを true に設定しないように CFC 定義を変更すると、ダンプに次のように表示されることにも注意してください。

プロパティなしでダンプ

そのため、合成されたアクセサーは (予想どおり) ありませんが、プロパティも表示されません (変数スコープの値の有無にかかわらず)。

この「プロパティ」とアクセサー設定の混同がよくわかりませんか? 確かに、アクセサー設定は、それらのアクセサー メソッドが作成されるかどうかにのみ影響するはずですか?

これを 1 つのプラットフォームでしか見ていなかったとしたらwriteDump()、 がプロパティ定義をどのように解釈するかという気まぐれに原因があると思います。しかし、動作は ColdFusion 11 でも同じであるため、実際には動作に何らかの違いがあるように見えますが、私にはよくわかりません。

誰でもこれを説明できますか?それを説明するドキュメントはありますか?そうじゃないなら... うーん... どうして?

ここでの私の根底にある懸念は、プロパティ値が「適切に」保存されておらず、コードをさらに実装すると問題が発生する可能性があることです。

更新: 少なくとも ColdFusion ではwriteDump()、プロパティのゲッターがある場合 (フラグが設定されているかどうかに関係なくaccessors)、プロパティ値がダンプに表示されるため、 の動作が変更されたようです。ただし、これは Lucee には当てはまらないため、まだ疑問符が残っています。

完全な開示のために、この質問は、私がブログでも行った質問の要約です (「CFML: アクセサーを理解しようとしている」)。私のブログはこのサイトの読者とは異なる読者を獲得しているため、重複は意図的なものです。

4

2 に答える 2

11

がなければaccessors=trueproperty宣言は単なるメタデータです。

ではaccessors=trueproperty宣言はゲッター/セッターの生成をトリガーするため、 apropertyvariablesスコープ項目であり、メソッドのペアでもあります。

コンストラクターで、スコープ項目に割り当てます (variables生成されたセッターを使用するのと同じです)。CFML がコンポーネントをダンプするとき、propertyメタデータと生成されたゲッターを確認し、それらのプロパティが持つ値を表示します (生成されたゲッターを簡単かつ安全に呼び出すことができます)。

于 2015-02-26T02:20:56.140 に答える
2

これがACF9を思いつきました。それまでは、プロパティ ドキュメントの定義は正しかった: cfproperty 宣言は単なるメタデータです。(ダンプ(getMetaData()を参照)。

ACF9 では、これは 3 つの理由で完全には正しくありませんでした:

  1. プロパティごとにgetter と setter が生成され、それらのアクセサが変数 scopeaccessors=trueから読み書きします。Cfproperty はもはや単なるメタデータではなく、インスタンスの動作に直接影響します。私はそれを実際の OO プロパティの CF バージョン (偶然に導入されたもの) と考えるのが好きです。

  2. cfdumpの実装は、プロパティの宣言に基づいて動作を変更します。property name;が定義されていて、メソッドが存在する (生成または実装されている)場合getName()は、ダンプのプロパティ セクションに追加されます。

  3. プロパティ属性は ORM を制御します。

これらの機能を知ったので、すべての (パブリック) CFC がダンプされたときに正しく見えるように設計します。プロパティ宣言 (+ ゲッター) は、表示したい場合にのみ使用します。さらに、ダンプによってのみ呼び出され、インスタンス化にコストがかからないメソッドを実装できます。

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 では機能しません。
  • ゲッターが公開されていないか、エラーが発生した場合、ダンプにはプロパティの空の文字列が表示されます (ここではわかりませんが、代わりにプロパティが欠落している可能性があります)。
  • 拡張 CFC のプロパティ宣言は無視されます。プロパティを 2 回宣言することは許可されていないため、継承を使用する ORM エンティティで頭痛の種になりました。したがって、ベース CFC で定義されているプロパティを表示することはできません。
  • Railo/Lucee はプロパティ タイプを無視しているようです。すべてのアクセサーは、文字列のみを受け入れて返します (getMetaData() を参照)。
  • マイナー: ACF で、アクセサーをアクティブ化するが、プロパティのゲッターとセッターを非アクティブ化するとproperty name="user" getter="false" setter="false";、ダンプに表示されますが、非表示にする必要があります。
于 2015-02-26T14:09:05.580 に答える