Hi guys,
I come from "Java world" so OOP is good know to me. But in codesys 3 I have some problems. I think codesys OOP is not so rich as Java and other high-level object oriented languages.
I have created two base interfaces - IProduct and IFactory (with method returning instance of IProduct)
Unfortunately, when I try to compile this I get an error: "Interface of overridden method 'GETPRODUCT' of interface 'IFACTORY' doesn't match declaration getProduct"
When I change the return type to the basic one - IProduct it works. I have checked that this work in Java (method declaration with return ProductTypeOne), so maybe it is also possible to do this in Codesys.
I want to mark that FactoryOne return only ProductTypeOne because I plan to use FactoryOne as a base FunctionBlock for FBs which should extends it and they should only return ProductTypeOne - eg. FB FactoryOneA, FactoryOneB,......
Also FactoryTwoA, FactoryTwoB,...... should return only ProcutTypeTwo and so on.
I hope you can point me out how to achieve this in codesys.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2017-03-01
Originally created by: scott_cunningham
IProduct is not the same as ProductTypeOne. Therefor the error is correct. You can return an instance of ProductTypeOne with your method (because it implements the interface and it will be cast automatically), but you cannot return the type ProductTypeOne as this is a different object. Maybe you meant to actually return the type ProductTypeOne (FBs are objects!) - but then you don't need the interface IProduct.
You can do this:
FBFactory...VARÂ Â MyProduct:ProductTypeOne;END_VARMETHODgetProduct:IProductgetProduct:=MyProduct;
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Yes, I want to return instance of object type ProductTypeOne.
As long as ProductTypeOne implements IProduct, everywhere IProduct is correct also ProductTypeOne is also correct because it can be cast to IProduct.
So if FactoryOne implements IFactory then method getProduct should return anything what implements IProduct.
But in Java I can also specify that method getProduct in FactoryOne can only return object which extends ProductTypeOne (they also implements IProduct). I hope that this is also possible in Codesys.
The benefit of "narrowing return type" is that later I can write without any casting
and call on that object methods specific to ProductTypeOne
My english is not so very well so maybe I haven't express correctly what I am trying to achieve.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2017-03-02
Originally created by: scott_cunningham
This code will not work:
product:ProductTypeOne:=FactoryOne.getProduct()
I think for what you are trying to do, you need to look at the REFERENCE keyword. You want to define product to be of type ProductTypeOne but have it actually be whatever the product is out of FactoryOne.
But I guess I am not understanding your use of interfaces... for me I understand it this way:
ProductTypeOne implements IProduct, but that doesn't mean ProductTypeOne is an IProduct. FBs can implement multiple interfaces, so whenever you write in code that you want to return an object IProduct, this does not mean the same as a ProductTypeOne.
So, the FB is required to have methods ProduceNoise and FlashLights, but also has other required features like a property NeedsUpdate and method ConnectToWiFi.
Now you do this:
PROGRAMPLC_PRGVAR  Toy1:ProductTypeOne;  Obj :IProduct:=Toy1;END_VARToy1.ProduceNoise();//validToy1.ConnectToWiFi();//validObj.ProduceNoise();//validObj.ConnectToWiFi();//notvalid-doesnotexisttointerface
With REFERENCE TO, you would get:
PROGRAMPLC_PRGVAR  Toy1:ProductTypeOne;  Obj :REFERENCETOProductTypeOne;END_VARToy1.ProduceNoise();//validToy1.ConnectToWiFi();//validObj.ProduceNoise();//validObj.ConnectToWiFi();//valid
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am new to codesys interfaces and have only done a bit of reading. A couple points come to mind that you may find helpful.
IProduct is a subset of ProductTypeOne. If I understand correctly the _QUERRYINTERFACE macro can be used to cast ProductTypeOne to IProduct. Check help for usage.
An object (FB) may implement multiple interfaces
FUNCTION_BLOCKFactoryOneIMPLEMENTSIFactory, IProductVAR_INPUTEND_VARVAR_OUTPUTEND_VARVAR
 Â
END_VARMETHODgetProduct : IProduct
  IF_QUERRYINTERFACE(...)THEN
    getProduct := ...;
  END_IF
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2017-03-02
Originally created by: scott_cunningham
QueryInterface can be used for two purposes: verify an object implements an interface, and cast the object. For it to work, the object must extend __System.IQueryInterface. Instead of remembering that all FBs must extend, I create a basic "ALL" interface that all FBs implement.
For example, I had a project where I wanted collections (arrays) of objects (because QueryInterface took too much time on my embedded controller for live-time determination)...
{attribute'reflection'}FUNCTION_BLOCKClassOdWordIMPLEMENTSIOdAll,IAllVAR_OUTPUT  {attribute'instance-path'}  {attribute'noinit'}  InstanceName  :STRING;  //object'sfullinstancename-automaticallyEND_VAR
And the collection object:
FUNCTION_BLOCKClassOdCollectionVAR
  Collection  : ARRAY[1..GVL_COLLECT.MAX_OBJECTS] OFIOdAll;
  ObjNames  : ARRAY[1..GVL_COLLECT.MAX_OBJECTS] OFSTRING;
  J    : INT;
  _ArrayOver  : BOOL;
  _BadObj  : INT;
  _DupeObj  : INT;
  _OverObj  : INT;
  _TotalObj  : INT;END_VARMETHODAddObjectVAR_INPUT
  Obj  : IAll; //general objectEND_VARVAR
  Cast: IOdAll; //object for the collectionEND_VAR//trytocasttheobjectIF(__QUERYINTERFACE(Obj, Cast))THEN
  //itisamember!
  //makesurehaven't already added this object
  FORJ:=1TO_TotalObjDO
    IFCollection[J] =CastTHEN
      //objectpointermatches-dupe!donotaddit
      _DupeObj:=_DupeObj+1;
      RETURN;
    END_IF
  END_FOR
 Â
  IF_TotalObj<GVL_COLLECT.MAX_OBJECTSTHEN
    _TotalObj:=_TotalObj+1;
    Collection[_TotalObj]:=Cast;
    ObjNames[_TotalObj]:=Obj.Instance;
  ELSE
    _ArrayOver:=TRUE;
    _OverObj:=_OverObj+1;
  END_IF
 Â
ELSE
  //objectwasnotamember!
  _BadObj:=_BadObj+1;END_IF
Hi guys,
I come from "Java world" so OOP is good know to me. But in codesys 3 I have some problems. I think codesys OOP is not so rich as Java and other high-level object oriented languages.
I have created two base interfaces - IProduct and IFactory (with method returning instance of IProduct)
And two Functions Blocks - ProductTypeOne, and FactoryOne which should return instances to ProductTypeOne
Unfortunately, when I try to compile this I get an error: "Interface of overridden method 'GETPRODUCT' of interface 'IFACTORY' doesn't match declaration getProduct"
When I change the return type to the basic one - IProduct it works. I have checked that this work in Java (method declaration with return ProductTypeOne), so maybe it is also possible to do this in Codesys.
I want to mark that FactoryOne return only ProductTypeOne because I plan to use FactoryOne as a base FunctionBlock for FBs which should extends it and they should only return ProductTypeOne - eg. FB FactoryOneA, FactoryOneB,......
Also FactoryTwoA, FactoryTwoB,...... should return only ProcutTypeTwo and so on.
I hope you can point me out how to achieve this in codesys.
Originally created by: scott_cunningham
IProduct is not the same as ProductTypeOne. Therefor the error is correct. You can return an instance of ProductTypeOne with your method (because it implements the interface and it will be cast automatically), but you cannot return the type ProductTypeOne as this is a different object. Maybe you meant to actually return the type ProductTypeOne (FBs are objects!) - but then you don't need the interface IProduct.
You can do this:
Yes, I want to return instance of object type ProductTypeOne.
As long as ProductTypeOne implements IProduct, everywhere IProduct is correct also ProductTypeOne is also correct because it can be cast to IProduct.
So if FactoryOne implements IFactory then method getProduct should return anything what implements IProduct.
But in Java I can also specify that method getProduct in FactoryOne can only return object which extends ProductTypeOne (they also implements IProduct). I hope that this is also possible in Codesys.
The benefit of "narrowing return type" is that later I can write without any casting
and call on that object methods specific to ProductTypeOne
My english is not so very well so maybe I haven't express correctly what I am trying to achieve.
Originally created by: scott_cunningham
This code will not work:
I think for what you are trying to do, you need to look at the REFERENCE keyword. You want to define product to be of type ProductTypeOne but have it actually be whatever the product is out of FactoryOne.
Try this:
But I guess I am not understanding your use of interfaces... for me I understand it this way:
ProductTypeOne implements IProduct, but that doesn't mean ProductTypeOne is an IProduct. FBs can implement multiple interfaces, so whenever you write in code that you want to return an object IProduct, this does not mean the same as a ProductTypeOne.
For example:
And now you make the product FB:
So, the FB is required to have methods ProduceNoise and FlashLights, but also has other required features like a property NeedsUpdate and method ConnectToWiFi.
Now you do this:
With REFERENCE TO, you would get:
I am new to codesys interfaces and have only done a bit of reading. A couple points come to mind that you may find helpful.
IProduct is a subset of ProductTypeOne. If I understand correctly the _QUERRYINTERFACE macro can be used to cast ProductTypeOne to IProduct. Check help for usage.
An object (FB) may implement multiple interfaces
Originally created by: scott_cunningham
QueryInterface can be used for two purposes: verify an object implements an interface, and cast the object. For it to work, the object must extend __System.IQueryInterface. Instead of remembering that all FBs must extend, I create a basic "ALL" interface that all FBs implement.
For example, I had a project where I wanted collections (arrays) of objects (because QueryInterface took too much time on my embedded controller for live-time determination)...
Created a base interface all object implement:
Created a interface for all OD objects:
Example object with automatic instance name!
And the collection object:
Some additional discussion can be found here: l viewtopic.php?f=11&t=5908 l .