1. Computing
An Introduction to COM Programming with Delphi (3 / 6)
What is the implements directive? What is the Method Resolution Clauses? Pseudo-Multiple Interface Inheritance. Interface properties and other fine tales of horror.
 More Delphi COM Lessons
• TOC
• Lesson 1
• Lesson 2
• Lesson 4
• Lesson 5
• Lesson 6
 Join the Discussion
"Post your views, comments, questions and doubts to this article."
Discuss!
 Related Resources
• COM / OLE / ActiveX programming with Delphi
 Download Source Code
• COMCodeExample3
• COMCodeNICEExample3
• COMCodeResolutionExample
• COMCodeMultipleExample
• COMCodeIPropExample
• COMCodeShapeDemo

Article written by Curtis Socha, brought to you by Zarko Gajic.

What is the implements directive?

Added to the Delphi 4 language, the implements directive allows you to implement your methods using a separate object instantiated within the class itself. Confusing, eh? I think a better way to explain this is shown in the flow chart shown below:
Notice that TMyClass never actually implements the procedure Something, even though IMyInterface has been assigned to it. What we are doing is saying to Delphi: "Hey, I'm not going to personally implement this procedure, but I know of a class that does. TMyImplementClass will implement this procedure for me!"

Delphi Implements Interface chart

As we can see, the implements directive is not really hard to comprehend. Although I didn’t really explain in the chart, TMyImplementClass is literally defined as just "class", not “class(TInterfacedObject, IMyInterface)”. The benefit of using this type of structure is that you can centralize all of your interfaces and the classes that implement the interface methods into a single class that contains only properties. This will allow you to keep your classes separate rather than having a giant class that implements the methods of a couple interfaces. The source code can become unwieldy and very annoying when you want only part of the class functionality, but you are forced to instantiate the entire class for just a few of it's methods. Refer to the following two coding examples starting with the UnWieldy code example. The extensively commented code should give you a much better understanding of how the implements directive works:

Download:

Method Resolution Clauses? What in the…?

A Method Resolution Clause is just a really cryptic way of saying that we have two different interfaces that have the exact same method names defined within. If both of these interfaces are being included into the same class and the implementation of each interface's method is supposed to be different, we have a problem. If we don’t fix it, then calling MyInterface1.MyProc would have the same result as MyInterface2.MyProc because the methods names are identical. Now you will need to refer to the following code example to see the syntax needed to solve this delimma: Resolution Code Example

Pseudo-Multiple Interface Inheritance

The books I have read called this a form of multiple inheritance. It is not true C++ style multiple inheritance, and from what I have read, and I am glad it is not. Thanks to the geniuses at Borland, it is actually very straightforward and simple. I have added the word pseudo and interface into the term multiple inheritance because this form of multiple inheritance does not concern itself specifically with inheriting from other classes, and that is what is usually understood when the term multiple inheritance is used. As you will see, it is actually a mix of both classes and interfaces.

That said, I want to keep this brief because there is only one point to this topic. It is this:

If more than one implementation of an interface appears in your class inheritance line, only the most recent one is active.

Look at the brief section of code listed below to get the gist of what I am trying to say:

IMyInterface = interface
  procedure SomeProc;
end;

TMyClass = class(TInterfacedObject, IMyInterface)
  procedure SomeProc;
end;

TMyOtherClass = class(TMyClass, IMyInterface)
  procedure SomeProc;
end;

Notice that TMyClass inherits IMyInterface and leads us to assume that TMyClass must also provide implementation for the procedure SomeProc. Then we put a spin on things by making yet another class called TMyOtherClass, that inherits TMyClass and IMyInterface. Using our rule for multiple inheritance, TMyOtherclass will only provide it’s own implementation of SomeProc. It will not retain any implementation from the TMyClass that it inherits. Download Multiple Inheritance Code Example.

Interface properties and other fine tales of horror

You may recall from earlier lessons that I had said that an interface couldn’t hold data. While this is a truth, it is not the complete truth. You can define read/write properties within an interface, just as you can within a class. There is one difference; data can only be accessed through the use of functions. This type of code is pretty much self-explanatory so I won’t get into depth about it. Let us look over the following code example:

IMyInterface = interface
  ['{C9B35200-DF7F-11D4-BDE0-00A024BAF736}']
  function GetFirstName : string;
  procedure SetFirstName(Name : string);
  property FirstName : string read GetFirstName 
                              write SetFirstName;
end;

TMyClass = class(TInterfacedObject, IMyInterface)
private
  FFirstName : string;
public
  function GetFirstName : string;
  procedure SetFirstName(Name : string);
end; 
{-------------------------------------------------}
function TMyClass.GetFirstName : string;
begin
  Result := FFirstName;
end;
{-------------------------------------------------}
procedure TMyClass.SetFirstName(Name : string);
begin
  FFirstName := Name;
end;

Download Interface Properties Code Example

Homework Assignment

In this homework assignment, we will need to solidify your understanding of how to use the method resolution, implements directive, interface properties, and multiple inheritance.

Homework Project:
You are going to create a program in which a TShape component will chase your mouse pointer around a specifically defined area. There are several rules that must be followed:

  1. You must use the 2 interfaces I have defined
  2. You must use the TGenericGolemClass I have defined. This class provides implementation for the methods defined in IGolemInterface. You must do the actual implementation however
  3. You must create a class called TGolemEntityClass. It instantiates the methods defined by IMouseInterface. (Hint: this will require you to use method resolution). It will also use the implements directive to create a local TGenericGolemClass.
  4. You must use the Application.OnIdle event to make your golem move fluidly
  5. You must use the Application.OnIdle event to make your golem move fluidly
  6. You are not allowed to directly instantiate a TGolemEntityClass. For example, the following code is not allowed

    var
      //Directly instantiating 
      //the class is a "no no"!
      MyGolem : TGolemEntityClass;    
      GolemInterface : IGolemInterface;
      MouseInterface : IMouseInterface;
    begin
      MyGolem := TGolemEntityClass;
      GolemInterface := MyGolem;
      MouseInterface := MyGolem;
    end;
    

    You can only instantiate your object through the use of interfaces!

Homework Summary
There is a big problem you will encounter when dealing with my 5th rule. I will give you a hint though because I am somewhat merciful. The 3rd method of grabbing an interface, which I explained during lesson 2, will point you in the right direction. Go ahead and compile the solution and run it to get an idea of how it should work. Note: There is apparently a threading error that occurs occasionally and I cannot figure it out. If you figure it out, let me know. I would be very happy to know what it is.

Download the Shape Demo.

An Introduction to COM Programming with Delphi: Table of Content
<< Previous Lesson (2): What is an Interface? How to implement an Interface? Describing the TInterfacedObject.
>> Next Lesson (4): A Com Object walk-a-bout. A Class Factory tour. Our first true COM Object program.

 

©2014 About.com. All rights reserved.