So, what is an Interface?

An interface is the heart of COM technology. When I use the word interface, do not confuse it with the visual display that the user interacts with. It is actually a fairly new reserved word incorporated into Delphi. An Interface is little more than group of abstract methods used to manipulate an object.

We established during the last lesson that an interface is not a class; it is an interface. Therefore, we must declare it as such. Let us explore some interface characteristics.

An interface is defined as type interface

You are to use the letter I to define your interface. I.E. "IMyInterface = interface"

An interface inherits from IUnknown

You cannot create an instance of an interface like you can a class that contains abstract methods

An interface cannot contain variables. (Read: It can contain properties as I will show you later on)

All functions and procedures declared in an interface are public virtual abstract methods. Even though you do not declare them this way, it is understood that is what they are.

Interfaces are reference counted

Now that we know more about what an interface can and cannot do, let us look at what it is like to declare an interface.

On GUIDs
I am sure you are wondering what the big string of crazy characters are. It is called a GUID and it stands for Globally Unique Identifier. Some people pronounce it as "gwid" or as "Gooey I.D.". Here some characteristics of a GUID:

Your interface will have a GUID unlike any other in the world

All interfaces and COM interfaces will have a GUID attached to it

You can create a GUID in Delphi by pressing CTRL-SHIFT-G

You are never to copy a GUID from one interface into another

Okay, but how do I implement an interface?

That is a good question. The answer is: You cannot implement an interface directly. You must create a class that will implement your interface. Refer to the coding example shown below.

The coding example listed above is about as simple as it can get while still having some type of visual functionality. Let's take a closer look at procedure TextBtnClick. Is there something missing? If you haven’t notice, we are not explicitly freeing the interface. This would appear to be a memory leak, but appearances are deceiving. As soon as the interface goes out of scope, Delphi will actually free the interface for you automatically! Interface's declared within a procedure or function will naturally fall out of scope when the procedure ends. Interface's declared within a class or are declared globally will naturally fall out of scope when the object is freed or the program ends.

Now we need to discuss Reference Counting. Every time you retrieve an interface to an object, e.g. IMyInterface := MyClass; Delphi will automatically increment its reference count using IUnknown's _AddRef function. When an interface falls out of scope, Delphi automatically calls IUnknown's ._Release function. If you haven't figured it out yet, IUnkown is an interface as well, and since we already know that an interface cannot implement the methods it defines, then you may be wondering where AddRef and Release come from. The answer is TInterfacedObject!

What in the world is TInterfacedObject?

TInterfacedObject and IUnknown are defined in system.pas. Before I can elaborate on this, we need to at least take a look at the code:

The code may look a little scary, but we are going to walk through this step-by-step since it is crucial that you understand reference counting in order to effectively program in COM. It is obvious from the code above that TInterfacedObject implements the methods defined in IUnkown. When you create a class that uses TInterfacedObject, you are essentially telling that class that it is going to be reference counted if an interface is assigned to it.

Let us look at simple piece of code so that I can describe the process that takes place.

When you use Direct Assignment to assign MyInterface to MyClass, the method _AddRef gets called automatically by Delphi. This says to MyClass, "Hey, an interface is referencing you! Were going to increment your reference count." If you were to change the aforementioned code to the following:

Notice that I added a new variable called MyInterface2. Since we are now setting 2 different interfaces equal to MyClass, guess what happens to the Myclass’s reference count? It becomes 2 because we now have two interfaces assigned to it!

You may be wondering about the _Release method that is implemented by TInterfacedObject. The _Release method automatically gets called for each interface assigned to a class that falls out of scope. Obviously, at the end of procedure DoThis, the program execution is going to return whence it came, therefore, your local class and interface declarations fall out of the scope in which they were declared. Since we have two interfaces defined, _Release will get called how many times? The answer is a bright shiny "2"! And once our reference count hits zero, then MyClass is automatically freed by Delphi. How nice and clean!

Homework Assignment

In this homework assignment, you will need to review the following source code: COMCodeExample2

Read through the code and the comments. I have provided the four methods you can use to retrieve an interface to an object. These four methods are necessary to fully understanding how interfaces work. The comments tell you exactly what, when, and how.

After you have finished reading through it, I want you to pick TWO of the methods shown in the code, (except for Direct Assignment which we discuss earlier), and build a program that uses both types of assignment. What the program does is not important to me. What is important is that you should play with interfaces because once we get to TCOMObjects, the real fun begins. We will not be playing with true COM objects for yet another week. Next week, we will go over the implements directive, method resolution, pseudo-multiple inheritance, and interface properties. We have a LOT to learn so I am going to be slamming you with information that you will need to digest. Make sure you do your homework.