- Objects, Components, and COM
- Abstraction and Class Modeling
- Encapsulation
- Polymorphism
- Inheritance
- Association Relationships
- One-to-One Relationships
- One-To-Many Relationships
- Class and Object Naming Conventions
- Component-Based Development
- Component-Based Development and COM
- COM-Definable Entities
- Component Coupling
- Summary
Inheritance
The final pillar of object orientation is that of inheritance. Fundamental to this concept is the capability to define the common methods and properties of a related group of classes in a base class. Descendants of this base class can choose to retain the implementation provided by the base class or can override the implementation on its own. In some cases, the base class provides no implementation whatsoever, and it is focused solely on the definition of an interface. We consider these types of base classes abstract because each subclass must provide the complete implementation. Regardless of the mode, the descendent class must maintain the definition of all properties and methods of its base class. Said in another way, the descendent class must define the same interface as its base. This is similar in concept to polymorphism, except that inheritance forces the implementation in a formal manner, such that Visual Basic can perform type checking at compile time.
Looking again at our CBond class, we notice that there is a BondType property to force certain alternative behaviors by the calculation methods. We can modify our CBond class into a single IBond base class and three subclasses called CCouponBond, CDiscountBond, and CConsolBond. We use IBond here (for Interface Bond) instead of CBond to coincide with Microsoft's terminology for interface implementation. Graphically, we represent this as shown in Figure 3.4.
Figure 3.4 An inheritance diagram for the IBond base class.
If we revisit our bond calculation functions in the context of inheritance, they might look something like Listing 3.3. Disregard the IBond_ syntax for now because it is a concept that we gain a thorough understanding of in our work in Part II of this book.
Listing 3.3 The CalculateBondPrice Method
' From the application Public Function CalculateBondPrice(BondType as Integer, _ IntRate as Single) As Single Dim OBond As IBond Select Case BondType Case BOND_TYPE_COUPON Set OBond = New CCouponBond Case BOND_TYPE_DISCOUNT Set OBond = New CDiscountBond Case BOND_TYPE_CONSOL Set OBond = New CConsolBond End Select CalculateBondPrice = OBond.BondPrice(IntRate) End Function ' From CCouponBond Implements IBond Public Function IBond_BondPrice(IntRate As Single) As Single Dim CouponPayment as Single Dim j as integer Dim p as single CouponPayment = IBond_CouponRate * IBond_FaceValue For j = 1 to IBond_BondTerm p = p + CouponPayment/(1 + IntRate)^j Next j p = p + IBond_FinalValue/(1 + IntRate)^IBond_BondTerm IBond_BondPrice = p End Function ' From CDiscountBond Implements IBond Public Function IBond_BondPrice(IntRate As Single) As Single IBond_BondPrice = FaceValue/(1 + IntRate) End Function ' From CConsolBond Implements IBond Public Function IBond_BondPrice(IntRate As Single) As Single Dim CouponPayment as Single CouponPayment = IBond_CouponRate * IBond_FaceValue IBond_BondPrice = CouponPayment/IntRate End Function
Although the application portion of this example might look somewhat similar to the polymorphic mechanism from before, there is an important distinction. Because we have defined these subclasses in the context of a base class IBond, we have forced the interface implementation of the base class. This, in turn, allows Visual Basic to perform early binding and therefore type checking at compile time. In contrast to late binding, this leads to better application performance, stability, and extensibility.
TIP
Any class definition that contains a Type property is a candidate for inheritance-based implementation.
Critics have chastised Microsoft for not implementing inheritance properly in Visual Basic in that it does not support a subclass descending from more than one base class, a concept known as multiple-inheritance. Although this lack of implementation technically is a true statement, in reality, multiple inheritance scenarios arise so infrequently that it is not worth the extra complexity that Microsoft would have had to add to Visual Basic to implement it.
Many critics would further argue that Visual Basic and COM, through their interface implementation technique, do not even support single inheritance properly and that the notion of the capability to subclass in this environment is ludicrous. Without taking a side in this debate, we can sufficiently state that interface implementation gives you some of the features afforded by single-inheritance, whether or not you want to formally define them in this manner. The particular side of the debate you might fall into is immaterial for the purposes of our framework development in Part II of this book.
Interface inheritance lends itself to maintainability and extensibilityessential attributes of enterprise applications as discussed in Chapter 1, "An Introduction to the Enterprise." If the implementation of a base method or property must change, we have to make the modifications only to the base class. Each descendent then inherits this new implementation as part of its interface implementation. If the base class physically resides in a different component than its descendants, something we will discuss later in this chapter, we only have to redeploy the component defining the base class.