We have alluded to the fact that a class may implement all, some, or none of the members of the interfaces that it defines. Any interface member that does not have an implementation is referred to as an abstract member. The purpose of an abstract member is to provide a member signature (a template, if you will) that can be implemented by one or more derived classes, generally in different ways.
Let us clarify this with an example. Recall from our discussion of inheritance that the CEmployee class defines and implements an IncSalary method that increments the salary of an employee. Recall also that the CExecutive and CSecretary derived classes override the implementation of the IncSalary method in the base class CEmployee.
Suppose that, in a more complete employee model, there is a derived class for every type of employee. Moreover, each of these derived classes overrides the implementation of the IncSalary method in the base class CEmployee. In this case, the implementation of IncSalary in the base class will never need to be called! So why bother to give the member an implementation that will never be used?
Instead, we can simply provide an empty IncSalary method, as shown here:
' Employee class Public Class CEmployee . . . Public Overridable Sub IncSalary(ByVal sngPercent As Single) End Sub End Class
Alternatively, if we want to require that all
derived classes implement the IncSalary method, we can use the
MustOverride
keyword, as shown here:
' Employee class Public MustInherit Class CEmployee . . . Public MustOverride Sub IncSalary(ByVal sngPercent As Single) End Class
As mentioned earlier, when using MustOverride
,
there is no End
Sub
statement
associated with the method. Note also that when using the
MustOverride
keyword, Microsoft requires that the
class be declared with the
MustInherit
keyword.
This specifies that we cannot create objects of type CEmployee.
In each of the previous cases, the IncSalary member of the base class CEmployee is an abstract member.
Any class that contains at least one abstract member is termed an abstract class. (Thus, the CEmployee class as defined earlier is an abstract class.) This terminology comes from the fact that it is not possible to create an object from an abstract class because at least one of the object’s methods would not have an implementation.
There are also situations where we might want to define a class in which all members are abstract. In other words, this is a class that only defines an interface. We might refer to such a class as a pure abstract class, although this terminology is not standard.
For example, imagine a Shape class called CShape that is designed to model the general properties and actions of geometric shapes (ellipses, rectangles, trapezoids, etc.). All shapes need a Draw method, but the implementation of the method varies depending on the type of shape — circles are drawn quite differently than rectangles, for example. Similarly, we want to include methods called Rotate, Translate, and Reflect, but, as with the Draw method, each of these methods require a different implementation based on the type of shape.
Thus, we can define the CShape class in either of the following ways:
Public Class Class2 Public Overridable Sub Draw( ) End Sub Public Overridable Sub Rotate(ByVal sngDegrees As Single) End Sub Public Overridable Sub Translate(ByVal x As Integer, _ ByVal y As Integer) End Sub Public Overridable Sub Reflect(ByVal iSlope As Integer, _ ByVal iIntercept As Integer) End Sub End Class
or:
Public MustInherit Class CShape Public MustOverride Sub Draw( ) Public MustOverride Sub Rotate(ByVal sngDegrees As Single) Public MustOverride Sub Translate(ByVal x As Integer, _ ByVal y As Integer) Public MustOverride Sub Reflect(ByVal iSlope As Integer, _ ByVal iIntercept As Integer) End Class
Now we can define derived classes such as CRectangle, CEllipse, and CPolygon. Each of these derived classes will (or must, in the latter case) implement the members of the base class CShape. (We won’t go into the details of such an implementation here, since it is not relevant to our discussion.)
We have
seen
that interfaces can be defined
in class modules. VB.NET also supports an additional method of
defining an interface, using the
Interface
keyword.
The following example defines the IShape interface:
Public Interface IShape Sub Draw( ) Sub Rotate(ByVal sngDegrees As Single) Sub Translate(ByVal x As Integer, ByVal y As Integer) Sub Reflect(ByVal iSlope As Integer, _ ByVal iIntercept As Integer) End Interface
Note that we cannot implement any of the members
of an interface defined using the Interface
keyword — that is, not within the module in which the interface
is defined. However, we can implement the interface using an ordinary
class module. Note the use of the
Implements
statement
(which was also available in VB 6, but could be applied only to
external interfaces):
Public Class CRectangle ' Implement the interface IShape Implements IShape Public Overridable Sub Draw( ) Implements IShape.Draw ' code to implement Draw for rectangles End Sub Public Overridable Sub Spin( ) Implements IShape.Rotate ' code to implement Rotate for rectangles End Sub End Class
Note also the use of the Implements
keyword in
each function that implements an interface member. This keyword
allows us to give the implementing function any name — it does
not need to match the name of the method (see the Spin method earlier
in this section, which implements the IShape
interface’s Rotate method). However, it is probably
less confusing (and better programming practice) to use the same
name.
The main advantage of using the Implements
keyword
approach to defining an interface is that a single class can
implement multiple interfaces, whereas VB.NET does not permit a
single class to inherit directly from multiple base classes. On the
other hand, the main disadvantage of the Interface
keyword approach is that no implementation is possible in the module
that defines the interface. Thus, all interface
members must be implemented in every class that
implements the interface. This can mean code repetition if an
interface member has the same implementation in more than one
implementing
class.
Get VB.NET Language in a Nutshell, Second Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.