|
The underlying
backbone of COM is the concept of Interfaces. COM - based classes simply
cannot be created without them. Of course, millions of VB 6.0 programmers
have been happily creating COM - based ActiveX DLL's and controls without
knowing diddlysquat about interface - based OOP programming, simply because
all the interface - based COM infrastructure and plumbing is done by VB
automatically "behind the scenes". However in VB.NET, interfaces
become visible, full-fledged citizens, and consequently deserve some study.
What's
an Interface?
An Interface is a collection of semantically
- related methods that describe a unique behavior that is to be supported
by a class. Interface - based programming encourages the reuse of behavior.
Once you've defined an interface, more than one class can choose to implement
its functionality. An interface in VB.NET always contains abstract members.
For example,
Public
Interface ICardAccount
Function GetBalance(AccountNumber as Integer) as Decimal
Property MaxCashAdvance() as Decimal
End Interface
Note
that the method and property signatures are defined, but they are abstract.
The implementation is up to the class that wishes to inherit the interface.
Unlike abstract base classes, interfaces never define data members, and
they never provide a default implementation.
When
you consider the fact that VB.NET (and most .NET languages, except perhaps
Eiffel) only support single inheritance, interface-based programming enables
a type to support a number of behaviors while simplifying the issues that
could arise from multiple base class inheritance.
In
VB.NET, when we want to extend the functionality of a given class, we
do so with the Implements keyword. So for example, if we had a
class SuperCardAccount, we could implement the ICardAccount interface
like this:
Public
Class SuperCardAccount : Inherits Account
Implements ICardAccount
Public Sub New()
End Sub
Public Sub New(ByVal AccountName as String)
MyBase.New(AccountName)
End Sub
' Implement the ICardAccount GetBalance method
Public Function GetBalance(AccountNumber as Integer) as Decimal
Implements ICardAccount.GetBalance
' Code to look up balance here
Return balance
End Function
Using
Interfaces
When a type supports a specific interface,
the caller can directly access the implemented members of the interface
from a valid object instance:
Dim
SCA as SuperCardAccount = new SuperCardAccount()
MessageBox.Show(SCA.MaxCashAdvance( ) )
We are asking the SCA instance for access
to the ICardAccount interface. If you need to be able to tell if a given
class implements a certain interface, you can use the TypeOf keyword:
If
(TypeOf(SCA) is ICardAccount) then
' rest of code logic here
We
can also have either a class or an interface derive from multiple base
interfaces as indicated above:
Interface
ISuperDuperCardAccount
Inherits ICardAccount, IAccount
End Interface
or,
for a class:
Class
SuperDuperAccount
Implements
ICardAccount
Implements
IAccount
' code here
End Class
The
.NET base classes make extensive use of interfaces. For example, fire
up WINCV and take a look at the socket class:
public
IAsyncResult BeginAccept(AsyncCallback callback, object state);
public IAsyncResult BeginConnect(System.Net.EndPoint remoteEP, AsyncCallback
callback, object state);
public IAsyncResult BeginReceive(byte[] buffer, int offset, int size,
System.Net.Sockets.SocketFlags socketFlags, AsyncCallback callback, object
state);
public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset, int size,
System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP,
AsyncCallback callback, object state);
public IAsyncResult BeginSend(byte[] buffer, int offset, int size, System.Net.Sockets.SocketFlags
socketFlags, AsyncCallback callback, object state);
public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, System.Net.Sockets.SocketFlags
socketFlags, System.Net.EndPoint remoteEP, AsyncCallback callback, object
state);
public void Bind(System.Net.EndPoint localEP);
IAsyncResult
is one of the interfaces defined in the System base class, and
it encapsulates the results of an asynchronous operation on an asynchronous
delegate. This is an example of using interfaces to standardize the public
methods or properties of multiple classes.
Encapsulating
functionality within objects helps us to support future change by creating
a separation between the public exposed properties, methods, and events
of our classes and the hidden implementation of their members. Provided
that the public interface is preserved, the private implementation can
safely be changed. This is one of the core concepts of OOP.
Interfaces
promote Good OOP programming
This
short article only gives an overall glimpse into how interface - based programming
can be useful.The main advantage of interface - based programming is the
OOP - oriented reusability of predefined behaviors for a method, and the
freedom to implement them in custom ways for a particular class. For example,
if your class needs to support "For each" iteration, you only
need to implement the IEnumerable interface and provide your own method
implementation for a GetEnumerator() method. Other valuable pre-built interfaces
are IComparable, ICloneable and IDictionary.
Another thing you can do is create and compile
your complete interface definitions in assemblies that can then be easily
referenced by your new classes, making it easy to extend and formalize
the implementations in related classes in your project.
It's
easy to see that interface - based programming, whether it involves your
own custom interfaces or those provided by the .NET Runtime base classes,
has many powerful features and the ability to help standardize and "OOPify"
your programming efforts.
Peter Bromberg is an independent consultant specializing in distributed .NET solutions
Inc. in Orlando and a co-developer of the EggheadCafe.com
developer website. He can be reached at pbromberg@yahoo.com
|