4

我在MATLAB中编写了一个非常简单的 GUI,可以转换温度。它旨在作为一类学生的教程。然而奇怪的事情发生了。与任何MVC设计模式一样,有一个模型对象、一个视图对象和一个控制器函数。为了设置 GUI 的输出字段(转换后的温度),您可以在控制器函数本身中运行此行:

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

其中views.outputTextField是一个 GUI 文本字段,用于显示转换后的温度,model.outTemp是转换后的温度。很简单。视图对象具有对所有 GUI uicontrols 的引用,这会使用模型对象中新转换的温度更新字段。

但是,我宁愿在视图对象中有视图函数,所以我尝试创建这样的一行:

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

这两种方法并不等效。匿名函数(又名 lambda)主体中的值被冻结,请参见下面的示例:

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

您可以执行以下操作以使其工作:

views.updateOutputField = @(outTemp) ...

如果您想知道 MATLAB 如何捕获工作区上下文,请使用FUNCTIONS匿名函数上的函数。

您的示例有点复杂,因为您的viewmodel存在于嵌套工作区中,但本质是相同的。

作为旁注:教学的荣誉也是 Matlab 课程中重要的设计模式(MVC)!

于 2009-10-27T21:59:49.993 回答
2

米哈伊尔有正确的答案。我会详细说明...

来自匿名函数的 MATLAB 文档:

匿名函数通常包括两种类型的变量:

  • 参数列表中指定的变量。这些通常随每个函数调用而变化。

  • 在表达式主体中指定的变量。MATLAB 捕获这些变量并在函数句柄的整个生命周期内保持它们不变。

当您在匿名函数中调用SET时,您可以访问两个结构变量viewsmodel. 这些值固定在创建匿名函数时的值。这对于存储在 中的图形句柄无关紧要views,因为它们永远不会改变(除非您正在删除和重新创建图形对象)。这就是为什么在匿名函数中调用GET可以正常工作的原因,因为它只使用views. 但是,值会model发生变化,因此您希望将它们作为参数传递给匿名函数。例如:

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

相反,当您创建updateOutputField函数时,您正在创建一个嵌套函数。嵌套函数可以访问它们嵌套在其中的外部函数中存在的变量,这就是您不必传递viewsmodel作为参数的原因。当这些变量在外部函数中发生变化时,这种变化在嵌套函数中也是可见的(与匿名函数不同)。

于 2009-10-27T23:21:26.683 回答