我使用OOP原理为我们的机器设计基本FB时被困。
一台计算机使用类似的模块:
module1 : BaseModuleFB;
module2 : BaseModuleFB;
一个模块(机器的某些部分)需要数据(例如位置,延迟等)的数据(例如位置,延迟等)。该数据将存储在配方中,以便将数据分组为结构中。
FUNCTION_BLOCK BaseModuleFB
VAR
Data : BaseModuleDataStruct;
END_VAR
现在,我有一台有额外要求的机器。而且还需要一些额外的数据。因此,我扩展了模块:
FUNCTION_BLOCK ModuleWithExtraFunctionFB EXTENDS BaseModuleFB
VAR
Data : ModuleWithExtraFunctionDataStruct;
END_VAR
上面的代码不会编译,因为可变数据已经在基类中使用。
顺便说一句,数据结构看起来像这样:
TYPE BaseModuleDataStruct:
STRUCT
position1:INT;
END_STRUCT
END_TYPE
TYPE ModuleWithExtraFunctionDataStruct EXTENDS BaseModuleDataStruct:
STRUCT
position2:INT;
END_STRUCT
END_TYPE
我想到的另一个选项是创建一个称为 data
的属性。
该属性可以被派生类推荐。
但是这种方法也失败了,因为您无法更改覆盖属性的类型。
也许有人对此有一些好主意?
谢谢。
I'm stuck while designing a basic FB for our machine using OOP principles.
A machine uses different modules like this:
module1 : BaseModuleFB;
module2 : BaseModuleFB;
A module (some part of the machine) needs data to function (like positions, delays, etc.) This data will be stored in a recipe so grouping the data in a struct makes sence.
FUNCTION_BLOCK BaseModuleFB
VAR
Data : BaseModuleDataStruct;
END_VAR
Now I have a different machine with some extra requirement. And also some extra data is needed. So I extend the module:
FUNCTION_BLOCK ModuleWithExtraFunctionFB EXTENDS BaseModuleFB
VAR
Data : ModuleWithExtraFunctionDataStruct;
END_VAR
The code above will not compile because the variable Data is already in use in the base class.
The Data structs look like this by the way:
TYPE BaseModuleDataStruct:
STRUCT
position1:INT;
END_STRUCT
END_TYPE
TYPE ModuleWithExtraFunctionDataStruct EXTENDS BaseModuleDataStruct:
STRUCT
position2:INT;
END_STRUCT
END_TYPE
Another option I thought of was creating a property called Data
.
This property can be overritten by the derived class.
But this approach also failed because you cannot change the type of the overridden property.
Maybe someone has some nice ideas about this?
Thanks.
发布评论
评论(1)
为什么不只是将结构的内容移动到功能块中:
如果您需要在结构中具有数据,最简单的方法就是使用多个结构(如 fred ):
如果您绝对必须在功能块内访问单个结构但是,以一种完全封闭的方式进行操作,但是,您可以将结构定义的责任传递给功能块的用户,并使用接口或指针注入它:
1。对于接口,我们将使用 operator。
然后在基本方法中您应该能够使用
_datapRovider.getModuleadata
以及在扩展方法_DatapRoviderb.getModulebData
中。2。对于原始指针,我们只能通过它们传递:
在您的第一个运行中,请调用
setData
两个功能块的方法。确保您正在传递正确的数据结构,以避免任何违规访问!然后,在基本方法中,您应该能够使用
pdata^.position1
和在扩展方法中pdata2^position2 position2
。3。我们还可以将两者结合起来,以直接访问结构,同时保留接口的类型安全性:
然后在基本方法中您应该能够使用
pdata^.position1
和在扩展中方法pdata2^.position2
。4。如果您希望不使用指针,则可以使用引用:
此选项由 Stefan roelofs < /a>在评论下面。
然后,在您的功能块内部,您可能需要使用
__ ISVALIDREF()
运算符来验证铸造/转换是否成功。之后,在基本方法中,您应该能够使用rdata.position1
和扩展方法rdata2.position2
。注意:您可能会收到许多C0410警告:
C0410:兼容性警告:对类型参考的属性的写入访问访问版本&lt的set-accessor; 3.5.10.0并写入参考,但称为版本&gt; = 3.5.10.0的Get-Accessor并写入值!使用操作员参考=如果要分配参考。
如果这使您烦恼,则可以禁用编译器(项目设置)中的C0410警告。
我在,您可以尝试导入它并与之相处。
Why not just move the contents of the struct into the function block:
If you need to have the data in structures, the simplest way would be to just use several structures (as pointed by Fred):
If you absolutely must access a single structure inside your function block, there is no simple way to do it in a completely enclosed way, however, you could pass the responsibility of defining the struct to the user of the function block and inject it either by using interfaces or pointers:
1. For interfaces, we will use the __QUERYINTERFACE operator.
Then in the base methods you should be able to use
_dataProvider.GetModuleAData
and in the extended methods_dataProviderB.GetModuleBData
.2. For raw pointers, we can just pass them:
In your Program on the first run call the
SetData
methods for both Function Blocks. Make sure you are passing the correct data struct to avoid any access violations!Then in the base methods you should be able to use
pdata^.position1
and in the extended methodspdata2^position2
.3. We could also combine the two for direct access to the structure while retaining the type safety of interfaces:
Then in the base methods you should be able to use
pdata^.position1
and in the extended methodspdata2^.position2
.4. If you'd prefer to not use pointers, you can use references instead:
This option was proposed by Stefan Roelofs in a comment below.
Then, inside your Function Blocks you may want to use the
__ISVALIDREF()
operator to validate that the cast/conversion was successful. After that in the base methods you should be able to userdata.position1
and in the extended methodsrdata2.position2
.NOTE: You may get many C0410 warnings:
C0410: COMPATIBILITY WARNING: A write Access to a Property of type REFERENCE calls the SET-Accessor for versions < 3.5.10.0 and writes the reference, but calls the GET-Accessor for versions >= 3.5.10.0 and writes the value! Use the operator REF= if you want to assign the reference.
If this annoys you, you may disable the C0410 warning in your compiler (Project Settings).
I uploaded an example PLCOpenXML file on GDrive, you can try importing it and play around with it.