PLC的面向对象编程(OOP)探秘1-类属性

        在讲解属性之前,先设定两个个前提。

                1,编程语言用纯文本ST语言(SIMATIC中称为SCL语言)。

                2,这里不探讨CODESYS的使用。只探讨OOP中晦涩的部分。

       

       下面就探讨属性   

        本文档探讨属性。对于结构化编程是没有属性这个概念的。但是属性是类最基本的概念。而类和对象是OOP最基本的概念。因此非常有必要对属性进行探讨。

        类可以有成员变量,那么属性是类的成员变量吗?   属性有什么特点?带着这些问题我们探讨属性。

第一步,创建一个类,及其属性。

        无论在SIMATIC中还是CODESYS中,类用FB(Function Block)。假设有一个类,类的名称是Cls_test。为这个类创建一个属性,属性名称是Prop,属性的数据类型是WORD。创建完毕如下图。

      ​​​   

       

        从对CODESYS的截图中我们可以观察到这个Prop属性下辖2个内容,Get和Set。而且观察Get和Set图标,我们发现这个图标与代码的图标(如Cls_test)很类似,暗示这里面是文本。所以,我们猜测Get和Set内部是代码。

        点击GET/SET进入后,果然是一个编程的界面。这个界面有变量声明部分和代码部分。这就证实了之前属性是代码的猜测。这是属性的第一个特征,属性是代码。

第二步,继续编程

       1,在类中声明2个成员变量:

                         Adr_Set, Adr_Get : POINTER TO WORD;

       2,在main中,声明一个对象。这个对象的类型是Cls_test。对象的名称是inst_test

       3,在main中编程,然后在线监控,如下图

        

        从图中,我们观察到,就象一个对象的成员变量一样,可以对这个属性进行读和写访问。所以属性的第二个特性出来了:可以如成员变量一样进行读写访问。

        观察上图代码第一行我们发现我已经给这个属性赋值1,但是在第二行读取该属性时,这个属性的值却是0。这是很奇怪的,同时上文提到属性是代码,但是这里又是变量?这是第二个疑问,不用急,本文将会回答这些疑问。

第三步,给属性写代码,读取属性的地址        

        在GET中,写入代码:  this^.Adr_Get := adr(Prop); //读取Prop的地址放入到Adr_Get中

        在SET中,写入代码:  this^.Adr_Set := adr(Prop); //读取Prop的地址放入到Adr_Set中

        进行在线观察,如下图

        观察上图红色方框内,我们发现get中的Prop和set中的Prop不是一个地址。这是一个现象。这个现象首先可能解释上图代码中为什么赋值Prop和读取到的的Prop不是一个值。因为本来地址就不同,所以就不是一个变量。这里我们得到一个重要启示,在OOP中写法相同的东西(上图的inst_test.Prop)不一定是一个东西。这是属性的第三个特征。

第四步,得到属性的所有隐含重要结论和特征

       之所以称为隐含结论是因为以下结论在所有CODESYS官方和非官方资料中都不全面。

        结论:经过测试,发现

        

        在get/set中,编译系统自动创建一个与属性名称类型相同,名称相同的变量Prop。所以分别读取set和get代码中Prop的地址会得到不同的地址。

        在get和set中,无论写xxxx := Prop;还是:Prop := xxxx;都会调用自己代码中的那个同名变量Prop。

         当在get以外写代码读取Prop,如:xxxx := obj.Prop。编译系统会调用属性的Get代码;然后将get代码中的Prop赋值给xxxx

         当在set以外写代码写入Prop,如:obj.Prop := xxxx。编译系统将xxxx赋值给Set代码中的Prop变量,并调用Set代码

        在get和set中,写法 This^.Prop:= XXX 会调用Set代码,同理写法:xxxx := this^.Prop会调用Get代码。所以在get 中写法xxxx := this^.Prop是危险的,因为可能存在无限循环调用自己的情况。同理,在set 中,写法This^.Prop:= XXX是危险的。         

        得到这些结论,我们再回顾以上的代码,发现一切都可以得到解释。

新问题:为什么OOP搞出属性这个东东?

        这是因为,属性有一个重要特点,就是可以将属性与一个只允许内部访问的private成员变量联系起来,并且可以设置只读或只写,或者读写。具体实现方法如下:

        我们在类Cls_test中声明一个变量_Prop,类型也是word,访问等级是private。

        在get中写入代码: Prog := _Prop;

        在set中写入代码: _Prog := Prop;

        这样就把属性Prop与成员变量_Prop联系起来了。可以通过操作属性从而操作成员变量。

        如果将这个属性设置为只读,那么只要删除set中的代码,那么其他任何外部程序都无法对_Prop成员变量进行写操作了。

        好了,到此有关属性的重要知识就结束了。其他有关属性的公开知识在各种文档中都可以找到,这里不再赘述。

        做个回顾。一行赋值代码在非OOP编程中,我们最多想到,编译系统给我们隐含增加了类型转换。但是到了OOP,一行赋值代码就可以触发其他代码的运行,还带有那么多花活。可见OOP编程是不直接的,不明显的,如果不注意也是危险的。当然OOP也一定会带来益处,我们将在后续的文档中和大家继续共同探讨。

          

        

                

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值