The Delphi Language, Part 2 - Interfaces
(Page 12 of 14 )
The Delphi language contains native support for interfaces, which, simply put, define a set of functions and procedures that can be used to interact with an object. The definition of a given interface is known to both the implementer and the client of the interface—acting as a contract of sorts for how an interface will be defined and used. A class can implement multiple interfaces, providing multiple known "faces" by which a client can control an object.
As its name implies, an interface defines only, well, an interface by which object and clients communicate. It's the job of a class that supports an interface to implement each of the interface's functions and procedures.
Note - Unlike Win32 Delphi, .NET interfaces to not implicitly descend from IInterface or IUnknown. As such, they no longer implement QueryInterface(), _AddRef, or _Release(). Typecasting is now used for type identity, and reference counting is built in to the .NET platform.
Defining Interfaces The syntax for defining an interface is very similar to that of a class. The primary difference is that an interface can optionally be associated with a globally unique identifier (GUID), which is unique to the interface. The following code defines a new interface called IFoo, which implements one method called F1():
type
IFoo = interface
function F1: Integer;
end;
Note that GUIDs are not required for .NET interface definitions, but they are required for Win32. Therefore, the use of GUID is only recommended when you need to maintain a multiplatform code base or want to engage in .NET COM Interop to interoperate between .NET and COM.
Tip - The Delphi IDE will manufacture new GUIDs for your interfaces when you use the Ctrl+Shift+G key combination.
The following code defines a new interface, IBar, which descends from IFoo:
type
IBar = interface(IFoo)
function F2: Integer;
end;
Implementing Interfaces
The following bit of code demonstrates how to implement IFoo and IBar in a class called TFooBar:
type
TFooBar = class(TObject, IFoo, IBar)
function F1: Integer;
function F2: Integer;
end;
function TFooBar.F1: Integer;
begin
Result := 0;
end;
function TFooBar.F2: Integer;
begin
Result := 0;
end;
Note that multiple interfaces can be listed after the ancestor class in the first line of the class declaration to implement multiple interfaces. The binding of an interface function to a particular function in the class happens when the compiler matches a method signature in the interface with a matching signature in the class. A compiler error will occur if a class declares that it implements an interface but the class fails to implement one or more of the interface's methods.
Interface Methods Made Easy - Let's face it, interfaces are great, but all of that typing to implement interface methods in a class can be a bummer! Here's an IDE trick to implement all the interface methods in just a few keystrokes and mouse clicks:
Add the interfaces you want to implement to the class declaration.
Place the cursor somewhere in the class and press the Ctrl+Spacebar keystroke combination to invoke code completion. The yet unimplemented methods show in red in the code completion window.
Select all the red-colored methods in the list by holding down the Shift key and using the keyboard arrow keys or mouse.
Press the Enter key, and the interface methods will be added automatically to the class definition.
Press the Ctrl+Shift+C keystroke combination to complete the implementation portion of the new methods.
Now all that is left to do is fill in the implementation portion of each method!
If a class implements multiple interfaces that have methods of the same signature, you must alias the same-named methods as shown in the following short example:
type
IFoo = interface
function F1: Integer;
end;
IBar = interface
function F1: Integer;
end;
TFooBar = class(TObject, IFoo, IBar)
// aliased methods
function IFoo.F1 = FooF1;
function IBar.F1 = BarF1;
// interface methods
function FooF1: Integer;
function BarF1: Integer;
end;
function TFooBar.FooF1: Integer;
begin
Result := 0;
end;
function TFooBar.BarF1: Integer;
begin
Result := 0;
end;
Note - The implements directive from Win32 Delphi is not available in the current version of the .NET Delphi compiler.
This chapter is from Delphi for .NET Developer's Guide, by Xavier Pacheco (Sams, 2004, ISBN: 0-672-32443-1). Check it out at your favorite bookstore today.
Buy this book now. |
Next: Using Interfaces, SEH >>
More .NET Articles
More By Xavier Pacheco