10-27-2017 03:57 AM
Hello together,
currently i'm working on a labview OOP project for instrument communication via serial port and GPIB. I use a class called 'generic device' which holds attributes like 'name' and 'calibration date'. The class 'generic device' has a setDeviceInfo method. Then i have several classes like '1534x Spectrometer' which inherit from 'generic device'. I want to force the programmer of the subclasses to include a setDeviceInfo method. To do so, i set the setDeviceInfo of 'genericDevice' to 'must be overridden'.
The idea is, that subclasses like '1534x Spectrometer' have more attributes like 'spectral range' and 'accuracy'. But when i create a VI to override setDeviceInfo with an input for the additional attributes, the VI is broken, since its connector pane doesn't match VI it overrides.
What is a good way to work around this issue?
Thanks in advance!
10-27-2017 04:37 AM
The reason for this is obvious (not sure if you know, but here it goes). If the interfaces are different, polymorphism is not possible.
Usually, I put this initialisation stuff in an init, and since the init is class specific, I name it Init Child A.vi, Init Child B.vi, etc. These methods are static, and might not even have an input class connector, just the specific class as output.
This does not force the programmer to implement the method.
The only way you can make such a method that is forced to be overwritten, is to make it accepts something general... Since you seem to be thinking in a good OO fashion, variants would be a big no-no.
What remains is a class. So, make a DiviceInfo.lvclass, and give each child a Init DeviceInfo For Child A.vi, GetDiviceInfo For Child A.vi, etc. But this just relays the problem to another class. You can't force the programmer to implement a DeviceInfo child.. While this pattern might be useful in some cases, it won't do much for your situation.
I'd say, a programmer who doesn't implement setDeviceInfo, won't get it working anyway... Or he just might, if the child just overwrites some methods, but then setDeviceInfo isn't really needed anyway.
In short, there is no compile time check to do this. You can set the parent method to force invoking the parent method. In this method, you could set a Boolean "device info set". If this Boolean isn't set, make other methods return an error (all methods should be set to always invoke parent method). Then you would have a (far fetched) run time check...
I'd just leave this one a little less perfect. The solutions are not worth the trouble...
10-27-2017 06:37 AM
wiebe@CARYA wrote:
Usually, I put this initialisation stuff in an init, and since the init is class specific, I name it Init Child A.vi, Init Child B.vi, etc. These methods are static, and might not even have an input class connector, just the specific class as output.
I have a Dynamic Dispatch "Initialize.vi" method for nearly all of my instrument classes. Generally, the Initialize.vi accepts a configuration file reference and I then parse out of the configuration file what is needed for that class. So instead of hard coding the device information, I save it in the application's ini file and read that file to setup my equipment.
10-27-2017 07:16 AM
@crossrulz wrote:
wiebe@CARYA wrote:
Usually, I put this initialisation stuff in an init, and since the init is class specific, I name it Init Child A.vi, Init Child B.vi, etc. These methods are static, and might not even have an input class connector, just the specific class as output.
I have a Dynamic Dispatch "Initialize.vi" method for nearly all of my instrument classes. Generally, the Initialize.vi accepts a configuration file reference and I then parse out of the configuration file what is needed for that class. So instead of hard coding the device information, I save it in the application's ini file and read that file to setup my equipment.
I have that too, when applicable.
In fact, my configuration file library can get\set classes (recursively) from a config file. This works more or less like a unflatten from string, but the data is in a readable config file. Not the wisest thing to do, a the class should be in charge of that... but it removes the dependency (e.g. not every class will depend on the config file class (NI's lib doesn't work for me)).
However:
+ that only works when the source is a file,
+ it also creates a dependency,
+ a 'clever' programmer might put the file reference in the class's private data, making the dependency very strong...
10-27-2017 09:46 AM
thanks for your replies.
BUT I can't use .ini-Files since I query the device information dynamically in the init VI.
10-27-2017 10:01 AM
Use the System Configuration API
10-30-2017 06:09 AM
@nollMarvin wrote:
thanks for your replies.
BUT I can't use .ini-Files since I query the device information dynamically in the init VI.
Red flag.
In order to get OOP doing the work for you as opposed to you working to keep OOP going, you need to be instantiating ONLY known typed of devices. It sounds like you are instantiating your device before you even know what type it is. This won't work.
Add an object to the data field of your Generic device class. When you find out the correct type of your device in Generic.Init, create an instance of the CORRECT class and do the initialisation in its own INIT method. "Generic Device" simply provides a public API for your specific versions.
I would recommend creating your "Generic Device" class so that all relevant methods are simply offloaded to the class contained within. Otherwise known as delegation or strategy pattern.
10-30-2017 07:46 AM
10-30-2017 08:41 AM
Norbert has probably just given a good answer..... I just need to find out which part of it applies......
10-30-2017 05:32 PM
Overloading, which is not supported in LVOOP. If it were the OP would have his solution.