85
End Sub End Class
The code still compiles without a problem, because Option
Strict is off. However, at runtime there
is a problem, as shown in Figur e 2- 2
.
Figure 2-2. A problem
The technique of accessing members through a generic object of type Object is called late binding. Late means that whether the desired member is really there is not known until the statement is
actually executed. In contrast, leaving Option
Strict on and accessing members only through
variables that have been declared as the appropriate type is known as early binding. Early means that whether the member access is legitimate is known at compile time.
Late binding is less efficient than early binding because additional checks are needed at runtime to determine whether the requested member actually exists on the runtime object and, if it does, to
access that member. The worst part of late binding is that it can mask certain program errors such as mistyped member names until runtime. In general, this is bad programming practice.
2.15 Interfaces
It is useful to make a distinction between a classs interface and its implementation. Conceptually, the interface of a class is the set of members that are visible to users of the class—i.e., the classs public
members. The public members are thought of as comprising the classs interface because they are the only way that code outside of the class can interact i.e., interface with objects of that class. In
contrast, the implementation is comprised of the classs code plus the set of members that are not public.
It is possible to take this interface concept further and separate interface definition from class definition altogether. This has benefits that will be shown shortly. To define an interface, use the
Interface statement:
Public Interface ISomeInterface Sub SomeSub
Function SomeFunction As Integer Property SomeProperty As String
Event SomeEvent _ ByVal sender As Object, _
ByVal e As SomeEventArgs _ End Interface
An interface declaration defines methods, properties, and events that will ultimately be implemented by some class or structure definition. Because interfaces never include any implementation, the
declarations are headers only—never any implementation code; End
Sub ,
End Function
, or End
Property statements; or property get or set blocks. There are no access modifiers
Public ,
Private , etc. because all members of an interface are public by definition. By convention, interface
names start with the letter I.
86
To provide an implementation for a given interface, it is necessary to define a class or structure. For example, the following class implements the interface defined earlier:
Public Class SomeClass This indicates that the class implements the methods,
properties, and events of the ISomeInterface interface. Implements ISomeInterface
This method implements the SomeSub method of the ISomeInterface interface.
Private Sub SomeSub Implements ISomeInterface.SomeSub ...
End Sub This method implements the SomeFunction method of the
ISomeInterface interface. Private Function SomeFunction As Integer _
Implements ISomeInterface.SomeFunction ...
End Function This property implements the SomeProperty property of the
ISomeInterface interface. Private Property SomeProperty As String _
Implements ISomeInterface.SomeProperty Get
... End Get
Set ...
End Set End Property
This event implements the SomeEvent event of the ISomeInterface interface.
Private Event SomeEvent _ ByVal sender As Object, _
ByVal e As SomeEventArgs _ Implements ISomeInterface.SomeEvent
End Class
The key elements of this class definition are: •
The class-declaration header is immediately followed by the Implements
statement, indicating that this class will expose the
ISomeInterface interface:
• Public Class SomeClass
• This indicates that the class implements the methods,
• properties, and events of the ISomeInterface interface.
Implements ISomeInterface This information is compiled into the class. Class users can find out whether a given class
implements a given interface by attempting to assign the object reference to a variable that has been declared of the interface type, like this:
Dim obj As Object Dim ifce As ISomeInterface
... Get an object reference from somewhere.
87
obj = New SomeClass ...
Try to convert the object reference to a reference of type ISomeInterface. If the object implements the ISomeInterface
interface, the conversion succeeds. If the object doesnt implement the ISomeInterface interface, an exception of
type InvalidCastException defined in the System namespace is thrown.
ifce = CTypeobj, ISomeInterface
• For each method, property, and event in the interface, there is a corresponding method,
property, or event in the class that has precisely the same signature and return value. The names dont have to match, although they match in the example.
• The declaration header for each method, property, and event in the class that implements a
corresponding item in the interface must have an implements clause. This is the keyword Implements
followed by the qualified name of the interface method, property, or event being implemented.
Additional things to note about implementing interfaces include: •
The access modifiers in the class-member declarations need not be Public
. Note that in the example all the members are marked as
Private . This means that the members are
accessible only when accessed through the ISomeInterface
interface. This will be shown in a moment.
• The class definition can include members that are not part of the implemented interface.
These can be public if desired. This results in a class that effectively has two interfaces: the default interface, which is the set of members defined as
Public in the class definition; and
the implemented interface, which is the set of members defined in the interface named in the Implements
statement. •
Classes are permitted to implement multiple interfaces. To access members defined by an interface, declare a variable as that interface type and manipulate
the object through that variable. For example: Dim x As ISomeInterface = New SomeClass
x.SomeFunction This code declares
x as a reference to an object of type ISomeInterface. Thats right: interface
definitions define new types. Declared in this way, x
can take a reference to any object that implements the
ISomeInterface interface and access all the members that
ISomeInterface defines, confident that the underlying object can handle such calls. This is a powerful feature of
defining and implementing explicit interfaces. Objects that explicitly implement an interface can be used in any context in which that interface is expected; objects that implement multiple interfaces can
be used in any context in which any of the interfaces is expected.
Interface definitions can inherit from other interface definitions in the same way that classes can inherit from other classes. For example:
Public Interface ISomeNewInterface Inherits ISomeInterface
Sub SomeNewSub End Interface
This defines a new interface called ISomeNewInterface
that has all the members of the ISomeInterface
interface plus a new member, called SomeNewSub. Any class or structure that implements the
ISomeNewInterface interface must implement all members in both interfaces. Any
88
such class is then considered to implement both interfaces and could be used in any context where either
ISomeInterface or
ISomeNewInterface is required.
2.16 Structures