4

温度を変換する非常に単純なGUIをMATLABで作成しました。これは、学生のクラスのチュートリアルとして機能することを目的としています。しかし、奇妙なことが起こりました。他のMVCデザインパターンと同様に、モデルオブジェクト、ビューオブジェクト、およびコントローラー関数があります。GUIの出力フィールド(変換された温度)を設定するために、コントローラー関数自体でこの行を実行できます。

set(views.outputTextField,'string',num2str(round(model.outTemp)));

ここviews.outputTextFieldで、は変換された温度を表示するGUIテキストフィールドであり、model.outTempは変換された温度です。かなり簡単です。ビューオブジェクトにはすべてのGUIuicontrolへの参照があり、これにより、モデルオブジェクトで新しく変換された温度でフィールドが更新されます。

ただし、ビューオブジェクトにビュー関数を入れたいので、次のような行を作成しようとしました。

views.updateOutputField = @()set(views.outputTextField,'string',...
    num2str(round(model.outTemp)));

以前と同じ行ですが、ビューオブジェクトの無名関数になっています。このようにして、コントローラーから関数を単純に呼び出し、views.updateOutputField();ビューロジックをコントローラーロジックから除外することができます。しかし、この方法は機能しません!(関数動作しget()ます。)

代わりに、次のことを行う必要があります。

views.updateOutputField = @updateOutputField

function updateOutputField()
    set(views.outputTextField,'string',num2str(round(model.outTemp)));
end

匿名関数を使用するだけでなく、関数を(冗長に)分離することで、再び機能します。何!?これは私には意味がありません。ビューオブジェクトとモデルオブジェクトはグローバルであり、無名関数はで機能しget()ます。誰かがここで何が起こっているのか手がかりを持っていますか?

4

2 に答える 2

3

両方のアプローチは同等ではありません。無名関数(別名ラムダ)の本体の値は凍結されています。以下の例を参照してください。

>> ii = 2;
>> val = @() ii+2;
>> val()
ans =
     4
>> ii=5;
>> val()
ans =
     4

あなたはそれを機能させるために以下を行うことができます:

views.updateOutputField = @(outTemp) ...

MATLABがワークスペースコンテキストをキャプチャする方法を知りたい場合は、FUNCTIONS無名関数で関数を使用してください。

viewとはネストされたワークスペースに存在するため、例はもう少し複雑ですmodelが、本質は同じです。

補足として:Matlabクラスで重要なデザインパターン(MVC)も教えてくれたことに対する称賛!

于 2009-10-27T21:59:49.993 に答える
2

ミハイルは正しい答えを持っています。少し詳しく説明します...

無名関数のMATLABドキュメントから:

匿名関数には通常、次の2種類の変数が含まれます。

  • 引数リストで指定された変数。これらは多くの場合、関数呼び出しごとに異なります。

  • 式の本体で指定された変数。MATLABはこれらの変数をキャプチャし、関数ハンドルの存続期間を通じて一定に保ちます。

匿名関数内でSETを呼び出すと、2つの構造変数viewsとのフィールドにアクセスしますmodel。これらの値は、匿名関数が作成されたときの値に固定されています。に格納されているグラフィックスハンドルは変更されないため、これは重要ではありませんviews(グラフィックスオブジェクトを削除および再作成する場合を除く)。で変更されていないグラフィックハンドルのみを使用するため、無名関数でGETを呼び出すと正常に機能するのはこのためviewsです。ただし、値はmodel変更されるため、引数として無名関数に渡す必要があります。例えば:

views.updateOutputField = @(model) set(views.outputTextField,'String',...
                                       num2str(round(model.outTemp)));

代わりに関数を作成すると、ネストされた関数updateOutputFieldが作成されます。ネストされた関数は、ネストされた外部関数に存在する変数にアクセスできます。そのため、引数として渡す必要はありません。これらの変数が外部関数で変更されると、その変更はネストされた関数でも表示されます(無名関数とは異なります)。viewsmodel

于 2009-10-27T23:21:26.683 に答える