Jump to content

Interface and Abstract Classes and how they pertain to LVOOP


Recommended Posts

I have just been reading up on topics of OOP in general and although I've used things similar to Interfaces and Abstract classes in LabVIEW, I didn't realize I was doing it. Due to differences between different text based OOP languages and LVOOP I was just wondering if I could get some of you to speak to these two concepts, whether they both really pertain to LVOOP, and possibly provide some actual examples (not just vehicle, shape, cookie cutter examples, but something I'd actually use) of when you'd define an interface vs an abstract class? I'm basically just looking for general information to help strengthen my understanding of these concepts, and most, if not all, examples out there are text based. While I can figure them out, it's much more time consuming, still leaves me with some grey area, and my brain tends to understand LabVIEW much better in the first place.

Edited by for(imstuck)
  • Like 1
Link to post
Share on other sites

Here's an older thread about interfaces in LabVIEW: http://lavag.org/top...0621-interface/

Thanks! My follow up question to this is then: why have the interface there? It looks like you wouldn't lose or gain any functionality if you stripped out the interface classes, as they have the exact same methods as the top level observer class. If you just had player and spectator inherit directly from observer, you'd still have to implement these 3 methods so what do you gain by putting the interface class in between? Is it just for code readability, or is it to further define the classes that inherit from observer (just in this case they only have the same 3 methods) and then any concrete classes can extend functionality even further? I have attached the UML from the other thread for reference

index.php?app=core&module=attach&section=attach&attach_rel_module=post&attach_id=406

Edited by for(imstuck)
Link to post
Share on other sites

That's a good thread.

We use a conceptually and practically simpler approach to interfaces. The tradeoff for the simplicity and clarity is that our approach does not allow a class to implement multiple interfaces. To date we have found the simplicity to be worthwhile.

The thread here http://lavag.org/topic/14213-strategy-pattern-example/page__hl__strategy__fromsearch__1 has a link to a document in which we discuss abstract classes and interfaces, what those mean, how we implement them, reasons to use them, and some use cases. (See especially the appendix.)

For more real-world examples you might see our slides from our NI Week 2012 presentation, "TS 8237 State Pattern Implementation for Scalable Control Systems."

The starting concepts, as I see them, are:

Abstract Class: "A class that can be used only as a superclass of some other class; no objects of an abstract class may be created except as instances of a subclass.“Larman, C., [Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development], Pearson, Upper Saddle River, 689 (2005).

Pure Virtual Method (Abstract Method): A method that has no implementation. This means that if we have a pure virtual method in a parent class, every child must implement that method. Budd, T. [An Introduction to Object-Oriented Programming, 3d ed.], Addison-Wesley, Boston, 170 (2002).

Interface: "A class can have abstract (or pure virtual) methods and nonabstract methods. A class in which all methods were declared as abstract (or pure virtual) would correspond to the Java idea of an interface.“Budd, T. [An Introduction to Object-Oriented Programming, 3d ed.], Addison-Wesley, Boston, 170 (2002).

We implement LabVIEW interfaces as abstract classes (never instantiated, by policy) with all "pure virtual methods" (in LabVIEW meaning we have implementations that do nothing).

The key advantages we derive from using interfaces are source code isolation and the ability to do design by contract.

Some of the many cases where we use interfaces are in the Factory Method Pattern and the State Pattern.

  • Like 1
Link to post
Share on other sites

Thanks Paul. I actually was just looking at your PDF from NI week yesterday and discussing it with one of my coworkers. Admittedly, it was a bit over my head but I'm taking it in slowly. I will look at the links you have provided when I have some time. I should also make a note that I didn't make in my reply to Asbo, I noticed that with the example link he provided, the concrete class is made to be an attribute of of the interface class. Is this always the case?

Link to post
Share on other sites

I noticed that with the example link he provided, the concrete class is made to be an attribute of of the interface class. Is this always the case?

No. I think (it's been a while since I looked at that thread in detail) that is something Mikael did to make it possible for a single class to implement multiple interfaces. We think that is too complicated for everyday use so we just use simple inheritance in the relationship between these. (Note that if every interface had a link to a concrete class that would be quite undesirable, since we would lose our source code isolation.)

Let me give you some examples of how we use interfaces.

1) State Pattern: State as Interface. We have a Context that invokes methods on State. State is an interface and simply defines the possible operations to perform. Context only has a reference to (i.e., "knows about" State). The concrete State classes that generalize (inherit from) State implement behaviors for the specific states. The developer of the Context does not need to know anything about those classes. We can add, remove, modify, completely restructure, or even swap different sets of concrete state classes without ever touching the Context. We have found that, among other things, it makes the overall application much easier to program. (It makes it a lot easier to focus on one thing at a time.)

2) Factory Method Pattern: creating State objects. In our approach to the State Pattern each method on a State class can determine what the next state is. (I think this is the most common approach. The GoF Designs Pattern books discusses two ways of doing this, but the distinction is not essential for this conversation.) We store the new state as an Enum and then use Factory Method Pattern to create the actual state object dynamically when we need it. Consequently the state objects do not have references to one another, which we found made a big difference when working in LabVIEW, especially on Real-Time.

Link to post
Share on other sites

I have just been reading up on topics of OOP in general and although I've used things similar to Interfaces and Abstract classes in LabVIEW, I didn't realize I was doing it.

Like so many things in programming, the word interface has multiple meanings. Here are the rough definitions I use:

interface (little "i") - A general term to indicate the set of inputs and outputs a component exposes to the outside world. Most of the time in LV discussions this is the kind of interface being referred to.

Interface (big "I") - A language construct that helps work around some of the limitations of single inheritance languages. These must be natively supported by the language. (Labview doesn't support them, so unless you've been poking around with the Interface framework I posted several years ago it's unlikely you'd unknowingly use them.) Most of the time when you encounter Interfaces in programming literature this is what they're talking about.

For an example of what Interfaces can do, suppose I have two unrelated classes, Baby and CellPhone, both of which have a Sleep method. I have an application where I want to call Baby.Sleep or CellPhone.Sleep without knowing whether the runtime object is a Baby or a CellPhone. So I define an ISleepable interface and give it a Sleep method. I also change the source code of the two classes so they properly implement the ISleepable interface. Since both classes implement a common Interface, I can cast the objects into an Interface and treat them as though they both inherit from ISleepable, even though they have unrelated class hierarchies.

IMO the ability to treat an arbitrary set of objects as though they all inherit from a single parent class, even though they are not related by inheritance, is the defining feature of an Interface. If you can't do it, it's not an Interface. (No disrespect to Paul or Mike intended, but imo what they are doing is using a class to formalize an interface, not create an Interface construct.)

------------

Typically abstract classes cannot be instantiated. Attempting to do so will result in a compiler error. In Labview there's no way to prevent someone from instantiating a class, so they don't exist in same sense as they do in text languages. I agree with Paul on what it means for a Labview class to be abstract--it's a regular class that is not intended to be instantiated at runtime. How you communicate that to other developers is up to you.

Link to post
Share on other sites

Typically abstract classes cannot be instantiated. Attempting to do so will result in a compiler error. In Labview there's no way to prevent someone from instantiating a class, so they don't exist in same sense as they do in text languages. I agree with Paul on what it means for a Labview class to be abstract--it's a regular class that is not intended to be instantiated at runtime. How you communicate that to other developers is up to you.

Ok, I unknowingly used "abstract" classes, scratch interfaces. Thanks for the link to your IF though; I looked it over last night and that makes sense. I don't currently have a need for it, but like so many other things, it's an idea to have in my "toolbox" so some light bulb goes off the situation arises where I may benefit from the concept.

Edited by for(imstuck)
Link to post
Share on other sites

I looked it over [the IF] last night and that makes sense. I don't currently have a need for it, but like so many other things, it's an idea to have in my "toolbox" so some light bulb goes off the situation arises where I may benefit from the concept.

My personal opinion of the IF...

It's functional and may have practical applications in rare situations, but it's too clunky to be general useful. Implementing an Interface takes too much code and isn't very easy for a typical LV developer to follow.

(There's another conversation about Interfaces here.)

Link to post
Share on other sites

...what they are doing is using a class to formalize an interface, not create an Interface construct.

Dave, Though I like your distinction of interface vs. Interface, I can't find this capitalization difference used elsewhere in programming language lingo. In looking at some examples of State Pattern in various languages, I do notice that care is taken in calling-it-what-it-is: Java and C# examples do implement State as an interface (and refer to it as such), while other language implementations call it an abstract class, and avoid use of the term 'interface' altogether.

I'll try to make this distinction in future discussion, thanks.

Link to post
Share on other sites

Though I like your distinction of interface vs. Interface, I can't find this capitalization difference used elsewhere in programming language lingo.

Nope, I made it up in 2009 in an attempt to clarify discussions (though I don't always follow the convention myself.) It's not a widespread convention (total number of followers = 1) so maybe I'm just adding to the confusion. All the literature I've ever read relies on context to know if they are talking about interfaces in general or interfaces as a construct or type. It works fine once you understand the difference, but for those who don't know the difference it can be very confusing. LV's lack of Interfaces compounds the confusion as there's no foundation for users to build up their understanding.

I'll try to make this distinction in future discussion, thanks.

Sometimes I'll use "api" instead of "interface" if I think there's potential for confusion.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Similar Content

    • By Marko Hakkarainen
      I had some time to learn about new interfaces and finally I could implement my collection class as I had envisioned. I didn’t want to use iterable and iterator names, because I thought that would have been too bold a claim.
      The original version of the collection class was (and is) used as a collection of sequence steps. Each element can be either a sequence command (send message, wait timer, wait complete etc.) or another collection of commands (sub-sequence). That’s the reasons for the labels and search method. Otherwise it is just a fancy (Rube Goldberg) array.
      Next method is recursive and it steps through all elements in the collection. Execute is only method, which requires override.
      For now, it’s at least an exercise in new interfaces. I don’t know if it’s useful enough to be in the code repository, but I can polish it up if needed.
       
      --
      Marko H
      Certified LabVIEW Architect
      www.optofidelity.com
      Iterable Collection LV2020.zip
    • By Zyl
      Hi everybody,
       
      I'm running into something I don't really understand. Maybe you can help me here !
      I've got a LVLIB that is used as an 'Interface': it exposes public VIs which wrap around public functions of a private class (see code attached) . The class is private because I want to force the users to use the 'interface' functions.
      In one of my interface VI, I create a DVR on the private class (Interface_init). The DVR is stored into a typedef (FClass_DVR.ctl) and this typedef is the 'reference' that link all the interface public functions.
      In TestCode.vi (which is not part of the lvlib and illustrates the standard code that a user can create to use my driver), I can call my public interface functions and link them without any problem.

      But as soon as I create an indicator on that reference (to create a state-machine-context-cluster for example), my TestCode VI breaks !

      The error returned is : This VI cannot use the LabVIEW class control because of library access scope. The LabVIEW class is a private library item and can only be accessed from inside the same library or libraries contained in that library.
      I understand that the class is private. But the DVR is contained into a public control. Using an In Place structure on that DVR into TestCode would not work, since the class is private. So why is the DVR control problematic at that point ? Creating it do not breaks any access protection...
      Am I missing something ?
      DVR Private POC.zip
    • By Brains
      Hi,
      Does anybody know the best way to make a copy of a byref object (open gds v4) at runtime and pass all the attributes values (including inherited attributes) to the new object?
      Thank you!
      Craig
    • By GregFreeman
      I currently have a project that I am refactoring. There is a lot of coupling that is not sitting well with me due to typedefs belonging to a class, then getting bundled into another class which is then fired off as event data.
      Effectively, I have class A with a public typedef, then class B contains ClassA.typedef and then class B gets fired off in an event to class C to be handled. Class C now has a dependency on class A which is causing a lot of coupling I don't want.
      For my real world example I query a bunch of data from our MES, which results in a bunch of typedef controls on the connector panes of those VIs. Those typedefs belong to the MES class. I then want to bundle all that data into a TestConfig class and send that via an event to our Tester class. But, now our tester has a dependency on the MES.
      I see a few ways to handle this. First is move the typedefs currently in the MES class, to the TestConfig class. The MES VIs will now have the typedefs from the TestConfig class on their connector panes, but at least the dependency is the correct "direction." Or, I can move the typedefs out of classes all together, but then I am not sure the best way to organize them. Looking for how others have handled these sorts of dependencies.
       
    • By bharathp
      Hi everyone.
      I need help regarding LVOOP implementation. I have gone through several examples and documents on LVOOP for quite some time, and finally decided to use it in this simple application. In my project LabVIEW application communicates between a PLC(local) and a server(TCP).I have used command pattern.For the server part i have created class and methods and it runs in a separate loop(i pass messages from main process loop). my problem is how can i make my main process using the same method? In QMH and state machine i can do it easily by checking condition and queuing next action how can i implement the same using OOP?
      I have tried passing the next command in the current method. Is it the right way to do?
      I am also thinking using a while loop inside methods for checking for validating conditions is it okay to do so?
      Or should i use QMH for the main process to send commands to the server loop?
      Or am i doing it all wrong?
      Thanks.
      LVOOP attempt.zip
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.