Interfaces

Team-Fly    

 
Application Development Using Visual Basic and .NET
By Robert J. Oberg, Peter Thorsteinson, Dana L. Wyatt
Table of Contents
Chapter 6.  VB.NET in the .NET Framework


Interface is a very fundamental concept in computer programming. A large system is inevitably decomposed into parts, and it is critical to precisely specify the interfaces between these parts. Interfaces should be quite stable, as changing an interface affects multiple parts of the system. In VB.NET, Interface is a keyword and has a very precise meaning. An interface is a reference type, similar to an abstract class, which specifies behavior as a set of methods , properties, and events. [2] An interface is a contract. When a class or structure implements an interface, it must adhere to that contract.

[2] We discuss events later in this chapter.

Interfaces are a useful way to partition functionality. You should first specify interfaces and then design appropriate classes to implement the interfaces. While a class in VB.NET can inherit implementation from only one other class, it can implement multiple interfaces.

Interfaces facilitate dynamic programsyou can query a class at runtime to see whether it supports a particular interface, and take action accordingly . Interfaces in VB.NET and .NET are conceptually very similar to interfaces in Microsoft's COM, but as we will see, they are much easier to work with.

In this section we will study the fundamentals of interfaces and provide illustrations using some small sample programs. Then we will restructure our Acme case study to take advantage of interfaces and explore their use in detail. After that we will examine several important generic interfaces in the .NET library, which will help us gain an understanding of how VB.NET and the .NET library support each other to help us develop powerful and useful programs.

Interface Fundamentals

Object-oriented programming is a useful paradigm for helping to design and implement large systems. Using classes helps us to achieve abstraction and encapsulation. Classes are a natural decomposition of a large system into manageable parts. Inheritance adds another tool for structuring our system, enabling us to factor out common parts into base classes, helping us to accomplish greater code reuse.

The main purpose of an interface is to specify a contract independently of implementation. It is important to understand that conceptually the interfaces come first .

Interfaces in VB.NET

In VB.NET Interface is a keyword, and you define an interface in a manner similar to defining a class. Like classes, interfaces are reference types. The big difference is that there is no implementation code in an interface; it is pure specification. Also note that an interface can have properties as well as methods (it could also have other members , such as events). As a naming convention, interface names usually begin with a capital I.

The IAccount interface specifies operations to be performed by classes that implement the IAccount interface.

 Interface  IAccount  Sub Deposit(ByVal amount As Decimal)    Sub Withdraw(ByVal amount As Decimal)    ReadOnly Property Balance() As Decimal    Sub Show() End Interface 

This interface illustrates the syntax for declaring the read-only Balance propertyyou specify the fact that it is a read-only property, followed by the property name and data type. This interface also specifies methods to be furnished by classes that implement this interface.

Implementing an Interface

In VB.NET you specify that a class or structure implements an interface, such as IAccount , by using the Implements keyword as shown in the following AccountC class. A class can inherit from a class and implement one or more interfaces. In this case the base class should appear first in the derivation list.

 Public Class  AccountC   Inherits Account   Implements IAccount  ... End Class 

In our example the classes AccountC and AccountW implement the interface IAccount that specifies methods to be implemented, and also inherit from the class Account that provides implementations for those methods. This is accomplished by simply calling the inherited version via the MyBase keyword. The result is that AccountC and AccountW indirectly implement the interface via inheritance.

We will examine a full-blown example of interfaces with the reservation-broker inheritance hierarchy later in the chapter, when we implement the next step of the case study.

As a small example, consider the program InterfaceDemo . The interface IAccount is defined, and two different classes, AccountC and AccountW , implement the interface. These implementations differ only in the Show method. The AccountC implementation performs console output to display the account balance, and AccountW uses a Windows message box. [3] The Deposit and Withdraw methods and the Balance property are all implemented in the Account base class, which is inherited by AccountC and AccountW , and accessed via the MyBase keyword.

[3] We will discuss Windows programming in Chapter 7. The example program has all needed references to libraries, and all you need to do to display a message box is call the Show method of the MessageBox class.

 graphics/codeexample.gif ' Account.vb Imports System Imports System.Windows.Forms  Interface IAccount  Sub Deposit(ByVal amount As Decimal)    Sub Withdraw(ByVal amount As Decimal)    ReadOnly Property Balance() As Decimal    Sub Show() End Interface  Public Class Account  Private m_balance As Decimal    Public Sub New()       m_balance = 100    End Sub    Public Overridable Sub Deposit(ByVal amount As Decimal)       m_balance += amount    End Sub    Public Overridable Sub Withdraw(ByVal amount As Decimal)       m_balance -= amount    End Sub    Public Overridable ReadOnly Property Balance() _     As Decimal       Get          Return m_balance       End Get    End Property End Class  Public Class AccountC   Inherits Account   Implements IAccount  Public Overrides Sub Deposit(ByVal amount As Decimal) _     Implements IAccount.Deposit  MyBase.Deposit  (amount)    End Sub    Public Overrides Sub Withdraw(ByVal amount As Decimal) _     Implements IAccount.Withdraw  MyBase.Withdraw  (amount)    End Sub    Public Overrides ReadOnly Property Balance() _     As Decimal Implements IAccount.Balance       Get          Return  MyBase.Balance  ()       End Get    End Property  Public Sub Show() Implements IAccount.Show   Console.WriteLine("balance = {0}", Balance)  End Sub End Class Public Class AccountW     ... End Class 
Using an Interface

You may call methods of an interface through an object reference to the class, or you may obtain an interface reference and call the methods through this interface reference. [4] The test program in the file InterfaceDemo.vb demonstrates both. We obtain the interface reference iacc by an implicit cast when we do the assignment to the object reference acc or accw . Note the polymorphic behavior of the call to Show , using console or Windows output depending on which object is being used.

[4] As we will see later in the chapter when we discuss explicit interface implementation, you can force a client program to use an interface reference and not a class reference.

 ' InterfaceDemo.vb  Imports System Module InterfaceDemo    Sub Main()       ' Use an object reference       Dim acc As AccountC = New AccountC()       acc.Deposit(25)       acc.Show()       ' Use an interface reference  Dim iacc As IAccount = acc  iacc.Withdraw(50)  iacc.Show()  ' Use interface reference for another class       ' that implements IAccount       Dim accw As AccountW = New AccountW()  iacc = accw   iacc.Show()  End Sub End Module 

Multiple Interfaces

Our first example illustrated two classes providing different implementations of the same interface. Another common scenario is for a class to implement multiple interfaces, and in VB.NET it is easy to test at runtime which interfaces are implemented by a class.

Our example program is MultipleInterfaces , which also illustrates interface inheritance. The interfaces IBasicAccount , IDisplay , and IAccount are defined in the file AccountDefs.vb .

 graphics/codeexample.gif ' AccountDefs.vb Interface IBasicAccount    Sub Deposit(ByVal amount As Decimal)    Sub Withdraw(ByVal amount As Decimal)    ReadOnly Property Balance() As Decimal End Interface Interface IDisplay    Sub Show() End Interface Interface IAccount  Inherits IBasicAccount, IDisplay  End Interface 
Interface Inheritance

Interfaces can inherit from other interfaces. Unlike classes in VB.NET, for which there is only single inheritance, there can be multiple inheritance of interfaces. In the following code snippet, the interface IBasicAccountDisplay is declared by inheriting from the two smaller interfaces, IBasicAccount and IDisplay . The advantage of factoring an interface into two smaller interfaces is an increase in flexibility. For example, a class implementing IBasicAccount may run on a server, where it would not be appropriate to implement IDisplay .

When declaring a new interface using interface inheritance, you can also introduce additional methods, as illustrated for a hypothetical interface IBasic-AccountDisplay .

 Interface IBasicAccountDisplay    Inherits IBasicAccount, IDisplay    Sub NewMethod() End Interface 
Implementing Multiple Interfaces

A class implements multiple interfaces by specifying each interface in its inheritance list and by providing code for the methods of each interface. A method may be implemented through inheritance from a base class. The file Account.vb in the MultipleInterfaces project illustrates two classes. Basic-Account implements only the interface IBasicAccount , but Account actually implements two interfaces. It explicitly implements IDisplay , and it implicitly implements IBasicAccount , via inheritance from BasicAccount .

 ' Account.vb Imports System  Public Class BasicAccount   Implements IBasicAccount  Private m_balance As Decimal    Public Sub New()       m_balance = 100    End Sub    Public Sub Deposit(ByVal amount As Decimal) _     Implements IBasicAccount.Deposit       m_balance += amount    End Sub    Public Sub Withdraw(ByVal amount As Decimal) _     Implements IBasicAccount.Withdraw       m_balance -= amount    End Sub    Public ReadOnly Property Balance() As Decimal _     Implements IBasicAccount.Balance       Get          Return m_balance       End Get    End Property End Class  Public Class Account   Inherits BasicAccount   Implements IDisplay  Public Sub Show() Implements IDisplay.Show       Console.WriteLine("balance = {0}", Balance)    End Sub End Class 
Using Multiple Interfaces

The test program MultipleInterfaces.vb illustrates using (or trying to use) the two interfaces with an Account object and a BasicAccount object. Both interfaces can be used with Account , but we cannot use the IDisplay interface with BasicAccount . In our code we perform a conversion from BasicAccount to IDisplay within a try block. The code compiles, [5] but we get a runtime InvalidCastException , which we catch. The program also illustrates that we can sometimes take a reasonable, alternative course of action if the desired interface is not available. In our case, we are able to perform the output ourselves , making use of the Balance property of the IBasicAccount interface.

[5] The compiler would flag an error message here if you had set the strict build option. To do this, go into Project Properties, and in Build properties, set the Option Strict to On.

 ' MultipleInterfaces.vb Imports System Module MultipleInterfaces    Sub Main()       Dim iacc As IBasicAccount       Dim idisp As IDisplay       ' Use an Account object, which has full       ' functionality       Dim acc As Account = New Account()       iacc = acc       idisp = acc       iacc.Deposit(25)       idisp.Show()       ' Use BasicAccount object, with reduced       ' functionality       Dim bacc As BasicAccount = New BasicAccount()       iacc = bacc       iacc.Withdraw(50)  Try   idisp = bacc  idisp.Show()  Catch e As InvalidCastException  Console.WriteLine("IDisplay is not supported")          Console.WriteLine(e.Message)          ' Display the balance another way          Console.WriteLine("balance = {0}", iacc.Balance)       End Try    End Sub End Module 

Here is the output from running the program:

 balance = 125 IDisplay is not supported Exception of type System.InvalidCastException was thrown. balance = 50 

Dynamic Use of Interfaces

A powerful feature of interfaces is their use in dynamic scenarios, allowing us to write general code that can test whether an interface is supported by a class. If the interface is supported, our code can take advantage of it; otherwise our program can ignore the interface. We could in fact implement such dynamic behavior through exception handling, as illustrated previously. Although entirely feasible , this approach is very cumbersome and would lead to programs that are hard to read. VB.NET provides the TypeOf Is operator to facilitate working with interfaces at runtime.

As an example, consider the program DynamicInterfaces , which uses the interface definitions and class implementations from our previous example. The test program illustrates using the VB.NET TypeOfIs keyword to check whether the IDisplay interface is supported.

 graphics/codeexample.gif ' DynamicInterfaces.vb Imports System Module DynamicInterfaces    Public Sub Main()       Dim iacc As IBasicAccount       Dim idisp As IDisplay       Dim bacc As BasicAccount = New BasicAccount()       iacc = bacc       iacc.Withdraw(50)       ' Check if idisp is IDisplay using TypeOf ... Is       If  TypeOf bacc Is IDisplay  Then          idisp = bacc          idisp.Show()       Else          Console.WriteLine("IDisplay is not supported")          ' Display the balance another way          Console.WriteLine("balance = {0}", iacc.Balance)       End If    End Sub End Module 

Here is the output from running the test program:

 IDisplay is not supported balance = 50 
The TypeOf is Operator

The TypeOf Is [6] operator dynamically checks if the runtime type of an object is compatible with a given type. The result is a Boolean value. The TypeOf Is operator can be used to check if an object refers to a class supporting a given interface, as illustrated in our DynamicInterfaces program.

[6] The VB.NET is operator is similar to type_id in C++ and the is operator in C#.

 If TypeOf bacc Is IDisplay Then    idisp = bacc    idisp.Show() Else 

The TypeOf Is operator is useful if you want to check whether an interface is supported but you don't need to directly call a method of the interface. Later in the chapter we will see an example of this situation, when we discuss the IComparable interface. If the elements of a collection support IComparable , you will be able to call a Sort method on the collection. The Sort method calls the CompareTo method of IComparable , although your own code does not.

Interfaces in VB.NET and COM

There are many similarities between .NET and COM. In both, the concept of interface plays a fundamental role. Interfaces are useful for specifying contracts. Interfaces support a very dynamic style of programming.

In COM you must yourself provide a very elaborate infrastructure in order to implement a COM component. You typically implement a class factory for the creation of COM objects. You must implement the QueryInterface method of IUnknown for the dynamic checking of interfaces. You must also implement AddRef and Release for proper memory management.

With VB.NET (and other .NET languages) the Common Language Runtime does all this for you automatically. You create an object via New . You check for an interface via TypeOf Is and obtain the interface by a type conversion assignment. The garbage collector takes care of memory management for you.


Team-Fly    
Top
 


Application Development Using Visual BasicR and .NET
Application Development Using Visual BasicR and .NET
ISBN: N/A
EAN: N/A
Year: 2002
Pages: 190

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net