首页 理论教育 IEC61131-3标准下的接口实现多继承功能

IEC61131-3标准下的接口实现多继承功能

时间:2023-06-27 理论教育 版权反馈
【摘要】:IEC61131-3标准采用单继承,因此,用接口实现多继承的功能。接口与抽象类配合,可提供方法、属性和事件的抽象。4)接口和抽象类都不能直接实例化。接口主要用于为多个不相关的子类提供通用功能。6)接口不允许递归。图1-36是例1-55接口继承的图形描述。例1-57中,接口ROOM有两个方法DAYTIME和NIGHTTIME。

IEC61131-3标准下的接口实现多继承功能

IEC61131-3标准采用单继承,因此,用接口实现多继承的功能。接口与抽象类配合,可提供方法、属性和事件的抽象。可认为接口是只包含抽象方法的抽象类,每个接口方法都表示一个服务契约,即能够提供什么服务,而不包含与实现有关的任何因素。

1.接口的声明

(1)接口的声明

接口声明的格式如下:

INTERFACE 接口名

接口本体;

END_INTERFACE

表1-67是接口的性能。

1-67 接口的性能

978-7-111-59695-0-Chapter01-181.jpg

接口本体可包含一组(隐式公有的)方法原型。方法原型是一个接口使用的受限制的一个方法的声明。方法原型的格式如下:

METHOD 方法名

变量声明

END_METHOD

方法原型(Method prototype)不包含任何算法(代码)和暂存变量,即它不包括实现。方法原型的存取符是默认的PUBLIC。因此,不需要再定义其存取符和返回值的数据类型。方法原型的变量声明包括VAR_INPUT、VAR_OUTPUT和VAR_IN_OUT变量的声明。

例1-54】接口的声明。

978-7-111-59695-0-Chapter01-182.jpg

(2)接口声明段的注意事项

接口声明段的注意事项如下:

1)接口方法不能是静态的,也不能使用任何存取符来限定,它的存取权限规定为PUBLIC。

2)接口定义的方法是抽象方法,因此,需要用继承(EXTENDS)来实现(IMPLEMENTS)有关方法。

3)接口给出没有实现代码的方法,具体应用时要再定义其接口的方法所需的服务内容。

接口和抽象类的主要区别是:

1)抽象类可包含非抽象的方法,即可以方法实现,而接口不包含非抽象方法,因此,没有方法实现。

2)抽象类要被子类继承,接口要被类的实例实现。

3)抽象类和接口都是引用数据类型,其变量就被赋值为子类或实现接口类的对象。

4)接口和抽象类都不能直接实例化。因为,它们都没有可实现的方法。

5)抽象类主要用于关系密切的多个子类对象。接口主要用于为多个不相关的子类提供通用功能。

6)抽象类的实现必须由其子类继承,并经覆盖所继承的方法来实现。而接口规定的方法的类可具有该接口的类型。因此,一个类可有多个接口,也就具有多个接口所具有的类型。

7)使用抽象类是为了代码复用,使用接口是为了实现多继承。

2.接口的继承

与类的继承一样,接口可以用EXTENDS来继承。IEC 61131标准规定类只能单继承,而接口可以多继承。

例1-55】接口的继承。

978-7-111-59695-0-Chapter01-183.jpg

接口的继承应遵循下列规则:

1)派生(子)接口继承不需要从它的基(父)接口进一步声明所有方法原型。例如,例1-55中,不需要再在继承的接口声明父类接口的方法原型。

2)如果基接口改变它的定义,所有派生接口(和它们的子接口)也改变其功能。

3)派生的接口可扩展一组原型方法,例如,除了基接口,它还有方法的原型和创建的新功能。

4)用关键字EXTENDS,一个接口可从一个或多个已经存在的接口(基接口)派生,即可实现多继承。

5)用于作为基接口的接口,其本身可以是一个派生接口。这样,它就可将继承的方法原型和它的接口一起继承到它的派生接口。

6)接口不允许递归。即其派生接口继承基接口,而基接口又继承派生接口。

接口继承和类继承的区别如下:

1)类继承不仅声明其父类,也声明其实现继承。接口继承只声明继承。这表示派生类可继承其父类的方法实现。而派生接口只继承父接口的方法原型,并没有继承父接口的实现。

2)类继承是单继承,接口继承是多继承。多个接口之间用逗号分隔。

3)接口不允许用OVERRIDE进行覆盖,类允许用OVERRIDE进行覆盖。

图1-36是例1-55接口继承的图形描述。接口DRIVE_A继承接口DRIVE_INTERFACE,它的方法START也同时被继承,此外,它也建立新方法A1。接口DRIVE_B继承接口DRIVE_A,它除继承其方法START和A1外,还建立新方法B1。

3.接口的实现

(1)在类的声明中接口的实现

类的声明中可实现单接口和多接口。例如,CLASS BB IMPLEMENTS A1,A2;表示类BB实现两个接口A1和A2。图1-37是例1-56接口实现的部分图形描述。

978-7-111-59695-0-Chapter01-184.jpg

图1-36 接口继承的图形说明

978-7-111-59695-0-Chapter01-185.jpg

图1-37 类的接口实现的部分图形描述

例1-56】类的声明中接口的实现和外部方法调用。

978-7-111-59695-0-Chapter01-186.jpg

程序A根据当前时间,执行类LIGHTROOM的实例MyRoom的方法NIGHTTIME()或DAYTIME()。这说明接口ROOM在类LIGHTROOM中声明,在程序A中,提供调用类LIGHTROOM的实例MyRoom,实现其方法。

978-7-111-59695-0-Chapter01-187.jpg

图1-38 继承和接口实现的关系

图1-38显示继承和接口实现的关系。(www.xing528.com)

(2)接口作为一个变量的类型

接口可作为一个变量类型,然后,该变量被引用到一个实现该接口的类的实例。该接口被使用前,它先被赋值到一个类的实例。对变量可使用的地方都可用该方法将接口作为一个变量类型。其格式如下:

变量名:接口名;

下列数值可被赋值到一个接口类型的变量:

1)一个实现该接口的类的实例。

2)一个从实现该接口的类派生的类的实例。

3)从该接口或该接口派生的接口的另一个变量。

4)NULL特定一个无效的引用。如果没有初始化,它也是变量的初始值。

一个接口类型的变量可以与同样的接口类型的变量进行比较,如果比较结果为TRUE,表示这些变量引用同一个类的实例或者这两个变量都是NULL。

例1-57】接口作为变量类型的实现。

978-7-111-59695-0-Chapter01-188.jpg

例1-57中,功能块ROOM_CTRL声明一个接口类型的变量RM作为输入变量,功能块程序中用RM=NULL的比较来判别接口是否是无效的引用。如果是,则返回。因此,接口作为一个变量类型时,必须先进行判别是否无效。

例1-57中,接口ROOM有两个方法DAYTIME和NIGHTTIME。类LIGHTROOM实现单接口ROOM。功能块ROOM_CTRL声明输入变量RM是接口类型的变量,调用该功能块时,将实现该接口的类的实例传送到该变量。该类中调用的方法就采用传送来的类的实例的方法。因此,采用这种方法,就可以传送实现不同接口的类的实例。

包含接口实现的类实例也可作为变量类型。格式如下:

变量名:类实例名;

例1-58】接口作为变量类型的调用。

如例1-57,应用程序如下:

978-7-111-59695-0-Chapter01-189.jpg

程序B用My_Room和My_Room_Ctrl实例化类My_ROOM和功能块My_ROOM_Ctrl,并调用功能块My_ROOM_Ctrl,调用时,它先传送类的实例My_ROOM到接口ROOM的输入变量RM。

图1-39说明了上面例1-58的层次关系。

978-7-111-59695-0-Chapter01-190.jpg

图1-39 接口、类和接口实现的关系

(3)接口和类的继承

1)接口继承:使用关键字EXTENDS。它是三个继承/实施层的第一层,例如,INTERFACE A1 EXTENDS A。

2)类的接口实现:使用关键字IMPLEMENTS,例如,CLASS B IMPLEMENTS A1,A2。

3)类的继承:使用关键字EXTENDS,例如,CLASS X EXTENDSB。

4.赋值尝试

赋值尝试用于检查类或功能块实例是否实现给定的接口。如果引用的实例是实现接口的类或功能块实例,则赋值尝试结果表示该实例是有效的引用,否则结果为NULL。因此,应检查赋值尝试的结果,使用前,其值应不等于NULL。

为安全的目的,赋值尝试分为接口引用到类(或功能块类型)的实例(向上转换)和从基类引用到派生类引用的一个引用(向下转换)两种。基类引用指派生类实例化后使用实例化后的对象来将实例化前所定义的基类转化为基类,然后输出的过程。

结构化文本编程语言中,用于接口的赋值尝试和用于引用的赋值尝试都使用“?=”符。

赋值尝试表示如果没有被赋值或不是有效引用,则将等号右侧的值赋值给其左侧的变量。

(1)接口的赋值尝试

接口的赋值尝试检查赋值尝试符号右侧的接口是否已经被赋值,如果没有被赋值,将右侧接口值赋值给左侧变量;如果已经被赋值,则将NULL赋值给左侧变量。

例1-59】接口的赋值尝试。

CLASS C IMPLEMENTS ITF1,ITF2 //类C实现接口ITF1和ITF2

END_CLASS

使用接口的赋值尝试程序:

978-7-111-59695-0-Chapter01-191.jpg

(2)引用的赋值尝试

与接口的赋值尝试类似,引用的赋值尝试检查赋值尝试符号右侧的引用是否是有效的引用。如果不是有效引用,将右侧引用值(例如类实例名)赋值给左侧变量;如果是有效引用,则将NULL赋值给左侧变量。

例1-60】引用的赋值尝试。

978-7-111-59695-0-Chapter01-192.jpg

使用引用的赋值尝试程序:

978-7-111-59695-0-Chapter01-193.jpg

978-7-111-59695-0-Chapter01-194.jpg

示例说明,当引用基类的实例名或引用基类实例时,由于不是有效引用,因此,引用的赋值尝试结果被赋值NULL。

(3)赋值尝试的表达方式

1)指令表编程语言中,用“ST?”操作符表示赋值尝试。

例1-61】指令表编程语言的赋值尝试。

978-7-111-59695-0-Chapter01-195.jpg

2)结构化文本编程语言中,用“?=”赋值尝试符表示赋值尝试操作。

例1-62】结构化文本编程语言的赋值尝试。interface1?=interface2; /*如果interface2是有效接口或引用,则赋值给interface1,否则interface1

被赋值NULL*/

3)图形编程语言中,用“?=”赋值尝试函数表示赋值尝试。

例1-63】图形编程语言的赋值尝试。

如图1-40所示,用赋值尝试函数表示赋值尝试。

978-7-111-59695-0-Chapter01-196.jpg

图1-40 图形编程语言中赋值尝试的表达

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈