方法

概述

方法是一种语言元素,类似于在功能块环境中可使用的功能。可将其视为包含相应功能块实例的功能。正如功能,方法包含返回值、以及用于临时变量和参数的自有声明部分。

此外,作为面向对象编程的方法,您可使用接口来整理可在项目中使用的方法。

注: 将方法或属性从 POU 复制或移动到接口时,将自动删除包含的实现。从接口复制或移动到 POU 时,需要指定所需的实现语言。

插入方法

要将方法分配至功能块或接口,可在应用程序树中选择相应的功能块或接口,单击绿色加号按钮并执行命令方法。或者,您也可以右键单击功能块或接口节点并从上下文菜单执行命令添加对象 > 方法

添加方法对话框中,输入名称、所需的返回类型实现语言以及 Access Specifier(请参阅下文)。如果方法不包含实现且实现由衍生功能块提供,请选择选项抽象。要选择返回数据类型,单击按钮 ...,打开输入助手...对话框。

访问说明符:出于兼容性考虑,访问说明符为选用项。说明符 PUBLIC 的作用等同于不设置说明符。

也可从选择列表中选择其中一个选项:

  • PRIVATE:方法上的访问限制为功能块。

  • PROTECTED:方法上的访问限制为功能块及其衍生物。

  • INTERNAL:方法上的访问限制为当前命名空间(库)。

单击打开进行确认。方法编辑器视图打开。

创建继承功能块时的输入助手

EcoStruxure Machine Expert 利用功能块内的继承简化面向对象的编程:当在继承自另一功能块的功能块上执行添加对象时,列出基本功能块中使用的动作方法属性转换元素以供选择:

  • 在基本功能块中定义的访问说明符PUBLICPROTECTEDINTERNAL动作方法属性转换元素可供选择。您可以调整继承对象的定义。在继承对象中,将相同的访问说明符分配给源元素。

  • 访问说明符PRIVATE动作方法属性转换不可选择,因为对基本功能块的访问受限。

声明方法

语法:

METHOD <访问说明符> <方法名称> : <返回数据类型>VAR_INPUT ... END_VAR

有关如何声明处理方法的接口的说明,请参阅接口一章

调用方法

方法调用也称为虚拟功能调用。有关更多信息,请参阅方法调用一章。

对于调用方法,请注意:

  • 方法的数据是临时的,仅在执行方法时有效(堆栈变量)。因此,在方法的每次调用时重新初始化在方法中声明的变量和功能块。

  • 仅允许接口中定义的方法具有输入、输出和输入/输出变量,但是没有主体(实现部分)。

  • 诸如功能这样的方法可具有额外输出。必须在方法调用期间分配它们。

  • 声明的访问说明符定义方法的调用方式:

    • INTERNAL:方法可以在其自己的命名空间中调用。

    • PROTECTED:方法可以在其自己的 POU 和衍生中调用。

    • PRIVATE:方法可以在其自己的 POU 中调用。

    • PUBLIC:方法调用不受限制。

注: 如果没有为方法定义返回值,则返回第一个输出的值。如果方法没有输出可用,则生成编译器错误消息。

实现方法

对于方法实现,请注意以下几点:

  • 在方法的主体中,允许访问功能块实例变量。

  • 如果需要,可使用 THIS 指针,其将始终指向当前实例。

  • 在方法中无法访问功能块的 VAR_TEMP 变量。

  • 方法可以对自身执行递归调用。

调用方法

使用以下语法来调用方法:

<return value variable> := <POU name> . <method name> ( <method input name> := <variable name> (, <further method input name> := <variable name> )* );

声明示例:

METHOD PUBLIC DoIt : BOOL
VAR_INPUT
    iInput_1 : DWORD;
    iInput_2 : DWORD;
    sInput_3 : STRING(12);
END_VAR

调用示例:

bFinishedMethod := fbInstance.DoIt(sInput_3 :='Hello World ', iInput_2 := 16#FFFF,iInput_1 := 16);
注: 调用方法时,会将方法的返回值指定给(例如)本地声明的变量。当省略输入变量的名称时,务必遵守声明顺序。

声明示例:

METHOD PUBLIC DoIt : BOOL
VAR_INPUT
    iInput_1 : DWORD;
    iInput_2 : DWORD;
    sInput_3 : STRING(12);
END_VAR

调用示例:

bFinishedMethod := fbInstance.DoIt( 16, 16#FFFF,'Hello World ');

递归方法调用

在实现内部,方法可以直接使用 THIS 指针,或者使用所分配的功能块的本地变量,来调用自身。

  • THIS^. <method name> ( <parameter transfer of all input and output variables>)

    使用 THIS 指针直接调用相关功能块实例。

  • VAR fb_Temp : <function block name>; END_VAR

    使用方法的对相关功能块进行临时实例化的局部变量来执行调用。

递归调用会生成编译器消息。如果方法具有 pragma {attribute 'estimated-stackusage : '<estimated_stack_size_in_bytes>'},则不生成编译器消息。有关实现示例,请参阅 Attribute estimated-stack-usage 章节

因此,指定方法名称不足以满足递归方法调用的要求。在此情况下,会生成以下编译器消息:

Program name, function or function block instance expected instead of
注: 递归调用在本质上是难以实现和调试的,可能造成不期望的影响,如内存问题和警戒时钟超时。
注意
不期望的应用程序问题
  • 仅在必要的地方实现递归算法。
  • 务必明确理解递归实现方法,并充分记录支持代码。
不遵循上述说明可能导致设备损坏。

功能块的特殊方法

方法

描述

Init

名为 FB_init 的方法默认隐式声明,但也可显式声明。它包含用于功能块的初始化代码,该代码在功能块的声明部分声明。请参阅 FB_init 方法

Reinit

如果为功能块实例声明了名为 FB_reinit 的方法,则会在复制实例后调用它(就和在线修改期间一样)并且将重新初始化新的实例模块。请参阅 FB_init, FB_reinit 方法

Exit

如果需要名为 FB_exit 的退出方法,则必须显式声明它。不能用隐式声明。在新的下载、复位前或所有已移动或已删除的实例的在线修改期间,将为功能块的每个实例调用 Exit 方法。请参阅 FB_exit 方法

属性接口属性每项都由 Set 和/或 Get 访问器方法构成。

也可在应用程序停止时进行方法调用

在设备描述文件中,可定义应当始终由库模块的特定功能块实例以循环任务的方式调用特定方法。如果该方法具有以下输入参数,则也会在活动的应用程序没有运行时处理它。

示例

VAR_INPUT
pTaskInfo : POINTER TO DWORD;
pApplicationInfo: POINTER TO _IMPLICIT_APPLICATION_INFO;
END_VAR

程序员可通过 pApplicationInfo 来检查应用程序状态,并定义应当发生什么。

IF pApplicationInfo^.state = RUNNING THEN <instructions> END_IF