Understanding how an interface works

Through trial and error and gnashing of teeth, I finally got my interface working. One part that I stumbled on was passing the reference to the receiving class to the sending class.

In my project, I run a number of different reporting classes. I have these all run from a thread. I’m using the Task class so I can update the UI safely, but I need to communicate back to the thread from various classes doing the report. Here is where I thought an interface would be the way to go and it works.

The part I’m not sure I understand is the passing of the thread class to the report class. I’ve defined the interface and the methods contained in the interface. In my thread class and the report class I create properties of the interface. But, nothing will work unless I pass the reference of the thread class into the constructor of the report class. Then, in the report class, I take that reference and assign it to the interface property. It seems that this would be assigning a variable of the wrong type - a thread to an interface.

Here is my question. Even without using an interface, I could pass the reference to the thread into the report class as a thread class and then call all the methods in the thread and this would be a lot simpler than setting up an interface. So why bother setting up an interface? Is it because we don’t want to have to know any more about the corresponding classes other than what the interface defines? With the interface, the two communicating classes can be assured that whatever happens within the classes regarding coding updates, the methods defined in the interface will always be there? It seems to me that this is not different functionality from just passing in the thread class, but instead it is a “contract” so to speak on what the communication will allow.

Do I understand this correctly? Things were a lot simpler when I was coding COBOL… :slight_smile:

If you haven’t read it already, the User Guide has a section on Interfaces that might help:

User Guide Book 1: Fundamentals, Chapter 5: Classes, Section 5: Interfaces

I did read that. That was my starting point. But, where in that section does it say that you need to pass the reference of the receiving class to the class sending back info? It would be really helpful if there was a full code example somewhere. If there is one, I couldn’t find it.

I did finally get this by using the Threads example from the RB Library book written by Aaron Ballman back in 2008. But, his example no longer works because he uses his interface to update the UI from the thread.

I don’t think I understand what you are asking. Passing references using interfaces does not behave differently. A variable declared as the Interface can contain a reference to any object that implements the interface.

The purpose of the Interface is to define the thread class as multiple data types. It is both Thread and Interface type, so it is perfectly legal to address it as either one. THIS is the genius of the interface.

[quote]Is it because we don’t want to have to know any more about the corresponding classes other than what the interface defines? With the interface, the two communicating classes can be assured that whatever happens within the classes regarding coding updates, the methods defined in the interface will always be there? It seems to me that this is not different functionality from just passing in the thread class, but instead it is a “contract” so to speak on what the communication will allow.
[/quote]
Exactly. You’re making a contract with the compiler so it can help protect you. In C, you’d have a reference to an unknown object that you could do whatever you want with it and if you did something illegal, your app would die a fiery death. The Interface allows the compiler to protect you from that.

Urghhh… Too… many… memories. Make it stop!!!

Couldn’t say it better even in my native language Tim!

Thank you. This is what I was trying to confirm. In my case, I could have simply passed in the reference to the thread without using an interface. For a very simple app, maybe this is ok, but using the interface I’m constrained to using the methods defined in the interface without worrying about how the code in the controlling thread may have been changed. So, using an interface doesn’t really provide functionality, it provides protection.

Below is the code from my thread when I create a report class. The third parameter is the thread class.

webSessReport = new WebSessionReport(pvcTemplate, sqlSessCursor, self)

Below is the constructor of the report class. Notice that I assign the thread class reference to the interface property. This was something I didn’t understand from the docs. How and why would you assign something of class thread to a property of type interface? OK, I found an example and tried it and it worked, but to me it looked strange. Notice I also assign the thread class reference to a property of type thread (theThread). I can access the methods via the interface or via the local reference of theThread. Of course, the interface protects me from unpredictable results.

[code]Sub Constructor(pvcTemplate As VC_Templates_ReadOnly, pvcSessionReports As VC_SessionsReport, pTheThread As ReportThread)

rptInterfacesub = pTheThread
theThread = pTheThread

End Sub
[/code]

I’m not a computer scientist and I admit that I’m pushing my envelope when using these features. I was just trying to confirm that my understanding was on the right track. Sometimes things work the way you want, but not the way you think they do.

More typically your parameter would be declared with the interface as the type:

Sub Constructor(pvcTemplate As VC_Templates_ReadOnly, pvcSessionReports As VC_SessionsReport, pTheSource As rptInterfacesub)

Now you can create a report supplying anything that implements the interface as the parameter, not just a thread.

I don’t think your example is really benefitting much from using an interface. Yes, the interface provides protection in that you will only be able to use the methods defined in the interface. But you can get some of that protection by making methods private (at least with your own classes).

I think interfaces are more used to do what Tim says above: allow an object to essentially have multiple types, which can provide ways for you to simplify your app design.

[quote=65050:@Paul Lefebvre]More typically your parameter would be declared with the interface as the type:

Sub Constructor(pvcTemplate As VC_Templates_ReadOnly, pvcSessionReports As VC_SessionsReport, pTheSource As rptInterfacesub)

[/quote]
Damn! I could have sworn I tried that and it didn’t work. This is one reason I was confused. I was trying so many things and I must have “fixed” something without realizing that what I did was fix something else.

[quote=65050:@Paul Lefebvre]I don’t think your example is really benefitting much from using an interface. Yes, the interface provides protection in that you will only be able to use the methods defined in the interface. But you can get some of that protection by making methods private (at least with your own classes).

I think interfaces are more used to do what Tim says above: allow an object to essentially have multiple types, which can provide ways for you to simplify your app design.

[/quote]
OK, but how do I get my report class to send some info back to the controlling thread? If this were a control or a subclass of the thread, I’d use an event. I want to report back to the controlling thread the progress of the report so that the thread can update the progress bar. I’m trying to use the Task class in the example.

I do have multiple type report classes, so I thought an interface was the way to go.

One idea: Add a ProgressUpdate method to the Interface. In the Thread, implement ProgressUpdate and have it set a property in the thread to a value that is used within the Run/UpdateUI events. The report class does something like this:

mTheSource.ProgressUpdate(progressValue)

But if you have multiple report classes, all of which take a thread as input then an interface is not really needed. If you had a single report class that could take multiple/different sources of input, then perhaps an interface would make sense.

Yes, I get that. I was questioning why you thought I didn’t need an interface.

And now, the penny has dropped. So, the easy way is the correct way and I don’t have to feel guilty. :slight_smile:
Thanks!