resource management。 In the sample code; the TaxableAmount property is the result of multiplying the data members _amount and _taxableRate。 For example; when calculating the taxable ine of a capital gain in Canada; you multiply the total amount by 50%。 Thus; the _taxableRate data member would have a value of 0。50。 Another item to note is that the declaration of TaxIne is lacking a Public scope; but has a NotInheritable keyword prefixed to the identifier。 When a class is prefixed with NotInheritable; it means that the class cannot be subclassed。 From a design perspective; the code is saying TaxIne is a shared class that should not be subclassed lest it affect the shared behavior。 The NotInheritable keyword can also be applied to a method; which means that the method cannot be overloaded or overridden。 You would use NotOverridable on a method when you do not want a derived class to change the behavior of the method。 Though to be able to use the NotOverridable keyword; you first need to define a method that overrides another method。 …………………………………………………………Page 202…………………………………………………………… 180 CH AP T E R 7 ■ L E A R N IN G AB OU T CO M P O N E N TS AN D C L AS S H I E R AR C H IE S The implementation of ITaxDeduction is similar to ITaxIne: NotInheritable Class TaxDeduction Implements ITaxDeduction Private _amount As Double Public Sub New(ByVal amount As Double) _amount = amount End Sub Public ReadOnly Property Amount() As Double _ Implements ITaxDeduction。Amount Get Return _amount End Get End Property End Class TaxIne and TaxDeduction are sealed classes because the functionality will be shared among implementations。 But is it wise to expose the interfaces and not the classes themselves? Interfaces are used to separate implementation from ideas。 Interfaces change very little; whereas implementations can and will change more often。 But if an implementation behaves like an interface in terms of changing interface signature; why not just expose the class itself? The answer is that sometimes you will expose the class; and sometimes you will expose the interface。 For the tax engine; exposing the sealed classes TaxIne and TaxDeduction would probably have been fine。 The rule of thumb is that you expose classes only when you are sure that the interface signatures of methods and properties will not change very often。 Implementing a Base Tax Account The ITaxAccount interface is also a candidate for base class functionality。 The implementation of this interface looks like this: MustInherit Class BaseTaxAccount Implements ITaxAccount Private _deductions(100) As ITaxDeduction Private _ines(100) As ITaxIne Public Sub AddDeduction(ByVal deduction As ITaxDeduction) _ Implements ITaxAccount。AddDeduction For c1 As Integer = 0 To 100 If _deductions(c1) Is Nothing Then _deductions(c1) = deduction Exit For End If Next End Sub …………………………………………………………Page 203…………………………………………………………… CH AP T E R 7 ■ L E AR N IN G AB O U T CO M P O N E N TS AN D C L AS S H I E R AR C HI E S 181 Public Sub AddIne(ByVal ine As ITaxIne) _ Implements ITaxAccount。AddIne For c1 As Integer = 0 to 100 If _ines(c1) Is Nothing Then _ines(c1) = ine Exit For End If Next End Sub Public ReadOnly Property Deductions() As ITaxDeduction() _ Implements ITaxAccount。Deductions Get Return _deductions End Get End Property Public ReadOnly Property Ine() As ITaxIne() _ Implements ITaxAccount。Ine Get Return _ines End Get End Property Public MustOverride Function GetTaxRate(ByVal ine As Double) As Double _ Implements ITaxAccount。GetTaxRate End Class Let’s take stock of what has been acplished and decide if the tax engine is plete from a base functionality perspective。 o Ideas have been defined for a plete tax engine。 o Some interfaces have been implemented in the form of base classes。 o Some interfaces have been implemented as sealed default implementations。 The tax engine can be considered plete because all of the interfaces have been defined and accounted for from a base functionality perspective as either base classes or default imple mentations。 It is does not mean that interfaces will always be implemented。 Sometimes some interfaces will not have a base functionality or base classes。 The important aspect to remember when defining the base functionality is to account for all interfaces to serve a purpose。 Do not define an interface as a placeholder for potential future functionality。 When seeing an interface; a user expects it to serve some type of purpose。 …………………………………………………………Page 204…………………………………………………………… 182 CH AP T E R 7 ■ L E A R N IN G AB OU T CO M P O N E N TS AN D C L AS S H I E R AR C H IE S ■Note The rule of thumb for interfaces is that once defined and put into production; they are not changed。 This rule of thumb is almost written in concrete。 You never change interfaces once they are in production