嗔秤戻幣�哉膵�云利匈嬉蝕湊蛸賜�塋床四衲���萩晦編報炎嘔囚^泡仟 ̄云利匈��
源平慎弌傍利 卦指云慕朕村 紗秘慕禰 厘議慕尺 厘議慕禰 TXT畠云和墮 〆辺茄欺厘議箝誓匂〇

VB2008貫秘壇欺娼宥(PDF鯉塀哂猟井)-及37何蛍

酔楯荷恬: 梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈 梓囚徒貧議 Enter 囚辛指欺云慕朕村匈 梓囚徒貧圭�鮗� ● 辛指欺云匈競何! 泌惚云慕短嗤堋響頼���誅卒亮茂�俊彭堋響��辛聞喘貧圭 "辺茄欺厘議箝誓匂" 孔嬬 才 "紗秘慕禰" 孔嬬��



                The parameter year could be justified because most countries do have specific tax rates  

          and implementations that are dependent on a year。 Yet the parameter province has no justifi

          cation。 Imagine trying to implement a British tax system and needing to specify a province�察 �

          when Britain does not collect ine tax at a local level。  

               A solution might be to redefine the interface as follows�此�



          Public Class Specifics  

              Public CanadianProvince As Province 

              Public AmericanState As State 

           End Class 



           Public Interface ITaxAccount  

              Sub AddDeduction��ByVal deduction As ITaxDeduction�� 

              Sub AddIne��ByVal ine As ITaxIne�� 

              Function GetTaxRate��ByVal ine As Double�察�ByVal year As Integer�察�_ 

              ByVal specifics As Specifics�� As Double 

              ReadOnly Property Deductions�┌� As ITaxDeduction�┌� 

              ReadOnly Property Ine�┌� As ITaxIne�┌� 

           End Interface 



                This new implementation has a specifics parameter�察�which is of type  Specifics。 The  

          purpose of Specifics is to define a class that is a hodgepodge of information that is needed to  

          determine the correct tax rate。 However�察�the Specifics approach is wrong�察�for the following  

          reasons�此�



               o  It requires knowing the implementation�察�which in the case of the interface is a bad idea。  

                  It is like going to a restaurant and saying you would like a waitress with blond hair。 



               o  Even if the type Specifics were acceptable�察�you would be adding and removing data  

                  members depending on how many tax systems you have implemented。 That is a bad  

                  idea and introduces maintenance issues。 



                The proposed solutions are not acceptable。 Additionally�察�there is still the problem of  

          having to figure out which tax rate to use。 



          Implementing Ideas with Specifics  



          To implement a solution�察�let¨s first start by fixing the TaxAccount class。 The modified version  

          will have some type of functionality that has data members that reference the year and prov

          ince。 Here is the modified and correct implementation of TaxAccount�此�


´´´´´´´´´´´´´´´´´´´´´´Page 207´´´´´´´´´´´´´´´´´´´´´´´

                           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 185 



Friend Class TaxAccount  

    Inherits BaseTaxAccount 



    Private _province As Province 

    Private _year  As Integer 



    Public Sub New ��ByVal province As Province�察�ByVal year As Integer��  

        _province = province 

        _year = year 

    End Sub 



    Public Overrides Function GetTaxRate��ByVal ine As Double��  As Double 

        If _year = 2008 Then 

            If _province = Province。Ontario Then 

                Return OntarioTax2008。TaxRate��ine�� 

            End If 

        End If 

        Throw New NotSupportedException�─�Year ; & _year & ; Province ; & _ 

            _province & ; not supported;�� 

    End Function 

End Class 



     The fix is to add a constructor that has province and year as parameters。 This sort of fix is  

quite mon�察�in that you don¨t change the interfaces�察�rather you change how the implemen

tations are instantiated。 Remember that when you instantiate a specific implementation�察�you  

know what functionality you want�察�and thus can give the additional parameters。 Once you are  

at the interface level�察�you should need to use only general ideas。  

     Now the TaxEngine class needs to be fixed。 TaxEngine is responsible for instantiating  

TaxAccount�察�and thus to instantiate a Canadian TaxAccount�察�TaxEngine needs additional  

parameters�察�as follows�此�



Friend Class TaxEngine  

    Inherits BaseTaxEngine 

    Public Overrides Function CreateTaxAccount�┌� As ITaxAccount  

        Return New TaxAccount��Province。Ontario�察�2008�� 

    End Function 

End Class 



     In the implementation of CreateTaxAccount�┌��察�the province Ontario and year 2008 are  

assumed。 Thus�察�whenever TaxEngine is instantiated�察�you need to make sure that the person is  

in Ontario and paying taxes for the year 2008。 The implementation solves nothing and skirts  

the issue of having to figure out how to deal with someone paying their taxes in British Columbia  

and the year 2009。 

     If you look at the implementation of TaxEngine�察�you will notice it is short。 One obvious solu

tion would be to create a TaxEngine type for each province and each year。 Here are two examples�此�


´´´´´´´´´´´´´´´´´´´´´´Page 208´´´´´´´´´´´´´´´´´´´´´´´

186      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 



          Friend Class Ontario2008TaxEngine  

              Inherits BaseTaxEngine 



              Public Overrides Function CreateTaxAccount�┌� As ITaxAccount  

                  Return New TaxAccount��Province。Ontario�察�2008�� 

              End Function 

          End Class 



          Friend Class BritishColumbia2009TaxEngine 

              Inherits BaseTaxEngine 



              Public Overrides Function CreateTaxAccount�┌� As ITaxAccount  

                  Return New TaxAccount��Province。BritishColumbia�察�2009�� 

              End Function 

          End Class 



               This solution is not that bad�察�because to be able to instantiate the correct tax engine�察�you  

          just need to define a factory that knows which class to instantiate。 But for the problem at hand�察 �

          this solution is extremely tedious�察�as you could end up with hundreds�察�if not thousands�察�of  

          TaxEngine definitions。 You would use the specific implementation approach when you have  

          fewer than a dozen variations。 

               The better approach is to add an interface specific to the Canadian tax system。 Think of it  

          as follows。 When you are instantiating the tax engine�察�you will need to know which tax system  

          to use。 The factory protects you from needing to know which type to instantiate�察�but there is  

          nothing wrong with giving some extra information that could be used by a factory。 

               Thus�察�the solution is to define a new interface called ICanadaTaxEngine。 The purpose of  

          ICanadaTaxEngine is to add factory methods that are used to instantiate types with parameters  

          specific to the implementation。 Following is the definition of the ICanadaTaxEngine。 



              Public Enum Province  

                  Alberta 

                  BritishColumbia 

                  Manitoba 

                  NewBrunswick 

                  NewfoundlandLabrador 

                  NovaScotia 

                  Nunavut 

                  Ontario 

                  PrinceEdwardIsland 

                  Quebec 

                  Saskatchewan 

                  Yukon 

              End Enum 



              Public Interface ICanadaTaxEngine  

                  Function CreateTaxAccount��ByVal province As Province�察�_ 

                    ByVal year As Integer�� As ITaxAccount 

                  Function CreateCapitalGain��ByVal amount As Double�� As ITaxIne 

              End Interface 


´´´´´´´´´´´´´´´´´´´´´´Page 209´´´´´´´´´´´´´´´´´´´´´´´

                           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 187 



     The definition of ICanadaTaxEngine contains two additional methods�此�



     o CreateTaxAccount�┌� is used to instantiate a tax account specific to a province and year。  



     o CreateCapitalGain�┌� is used to instantiate an ine using the Canadian capital gains  

       calculation。 



     Thus�察�the implementation of TaxEngine bees the following。 



Friend Class TaxEngine 

    Inherits BaseTaxEngine 

    Implements ICanadaTaxEngine 



    Public Overrides Function CreateTaxAccount�┌� As ITaxAccount  

        Return New TaxAccount��Province。Ontario�察�2008�� 

    End Function 



    Public Overloads Function CreateTaxAccount��ByVal province As Province�察�_ 

                                               ByVal year As Integer��  _  

    As ITaxAccount _ 

        Implements ICanadaTaxEngine。CreateTaxAccount 

        Return New TaxAccount��province�察�year�� 

    End Function 



    Public Function CreateCapitalGain��ByVal amount As Double�� As ITaxIne _ 

        Implements ICanadaTaxEngine。CreateCapitalGain 

        Return New TaxIne��amount�察�0。50�� 

    End Function 

End Class 



     In the modified implementation of TaxEngine�察�the class still derives from BaseTaxEngine�察 �

fulfilling the requirement of being a general tax engine。 However�察�for the additional require

ments of the Canadian tax system�察�we implement the ICanadaTaxEngine interface。  

     Defining a specific interface that implies a certain implementation is fine�察�because the  

specific interface is not bound to a certain implementation。 The better way to understand  

this implementation technique is to consider the specific interface as a characteristic that  

an implementation is capable of supporting。 This goes back to the shape example�察�where a  

square can support both the ISquare and IRectangle interfaces。  



Using the Tax Engine 



The last step is to use the tax engine to calculate some taxes。 The following is an example of  

calculating the taxes for Ontario in 2008。 



Dim engine As ITaxEngine = EngineCreator。CreateCanadianTaxEngine�┌� 

Dim canadaEngine As ICanadaTaxEngine = TryCast��engine�察�ICanadaTaxEngine�� 

Dim account As ITaxAccount = canadaEngine。CreateTaxAccount��Province。Ontario�察�2008�� 



Dim ine As ITaxIne = engine。CreateIne��100�� 

Dim capitalGain As ITaxIne = canadaEngine。CreateCapitalGain��100�� 


´´´´´´´´´´´´´´´´´´´´´´Page 210´´´´´´´´´´´´´´´´´´´´´´´

188      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 



          account。AddIne��ine�� 

          account。AddIne��capitalGain�� 



          Dim deduction As ITaxDeduction = engine。CreateDeduction��20�� 

          account。AddDeduction��deduction�� 

          Dim taxToPay As Double = engine。CalculateTaxToPay��account�� 

          Console。WriteLine�─�Tax to pay �──�& taxToPay & ;��;�� 



               Notice the definition of the variables engine and canadaEngine。 This is fine�察�because what  

          we are doing with the interfaces is choosing a characteristic that can be dynamically queried。 



          Learning More About Inheritance and  

          Type Casting 



          This chapter introduced interfaces and ponents�察�and delved deeper into inheritance。 Here�察�I¨ll  

          provide more details about inheritance and type casting。 



          More Inheritance Details 



          In this section�察�I am going to clearly lay out how inheritance works in Visual Basic。 I will present  

          examples of usage for six scenarios。 Each example is followed by a list explaining the key points  

          to understand。 My goal is to illustrate all of the possible scenarios so that you have a reference  

          to how inheritance works。  



          *Note  All of the examples demonstrate using methods�察�but it is possible to apply the same inheritance  

          techniques using properties。 



          Scenario 1�此�Overloading Base Class Functionality 



              Class Base  

                  Public Sub Method�┌� 

                      Console。WriteLine�─�Base。Method;�� 

                  End Sub 

              End Class 



              Class Derived  

                  Inherits Base 

                  Public Overloads Sub Method�┌�  

                      Console。WriteLine�─�Derived。Method;�� 

                  End Sub 

              End Class 


´´´´´´´´´´´´´´´´´´´´´´Page 211´´´´´´´´´´´´´´´´´´´´´´´

                          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 189 



    Module Test  

        Public Sub Run�┌�  

            Dim derivedCls As Derived = New Derived�┌� 

            Dim baseCls As Base = derivedCls 



            ' Calls Derived。Method 

            derivedCls。Method�┌� 

            ' Calls Base。Method 

            baseCls。Method�┌� 

        End Sub 

    End Module 



    o  Keywords used�此�Overloads in the derived class to indicate the method is being overloaded。 



    o  Overloading a method means to change the functionality of the method in the derived class。 



    o  Which method is called in the inheritance depends on the type of the variable on which  

       the method is called。 Thus�察�if the variable is of type Base�察�Base。Method�┌� is called�察�if the  

       variable is of type Derived�察�Derived。Method�┌� is called。 



Scenario 2�此�Overriding Base Class Functionality 



    Class Base  

        Public Overridable Sub Method�┌�  

            Console。WriteLine�─�Base。Method;�� 

        End Sub 

    End Class 



    Class Derived 

        Inherits Base 

        Public Overrides Sub Method�┌�  

            Console。WriteLine�─�Derived。Method;�� 

        End Sub 

    End Class 



    Module Test  

        Public Sub Run�┌�  

            Dim derivedCls As Derived = New Derived�┌� 

            Dim baseCls As Base = derivedCls 



            ' Calls Derived。Method 

            derivedCls。Method�┌� 

            ' Calls Derived。Method 

            baseCls。Method�┌� 

        End Sub 

    End Module 


´´´´´´´´´´´´´´´´´´´´´´Page 212´´´´´´´´´´´´´´´´´´´´´´´

190       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 



               o Keywords used�此�Overridable in the base class to indicate the method behavior can be  

                 changed in the derived class。 Overrides is used in the derived classes to indicate a method  

                 with the new behavior。 Multiple levels of inheritance require multiple usages of Overrides。 



               o Overriding a method means to change the behavior of the method in the base class to  

                 that of the derived class。 If there are multiple levels of inheritance�察�then the functionality  

                 used is the instantiated type。  



               o You can also define a Overridable base class method using the MustOverride keyword。  

                 The difference between Overridable and MustOverride is that Overridable has a method  

                 or property implementation in the base class�察�whereas MustOverride has no implemen

                 tation in the base class。 



          Sc
卦指朕村 貧匯匈 和匯匈 指欺競何 壘��16�� 家��13��
酔楯荷恬: 梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈 梓囚徒貧議 Enter 囚辛指欺云慕朕村匈 梓囚徒貧圭�鮗� ● 辛指欺云匈競何!
梁椣戻幣�� 梁心弌傍議揖扮窟燕得胎��傍竃徭失議心隈才凪万弌誌育断蛍�輌臆惨軼僑〃�燕慕得珊辛參資誼持蛍才将刮襲潜��範寔亟圻幹慕得 瓜寡追葎娼得辛參資誼寄楚署衛、持蛍才将刮襲潜填��