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

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

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



                When you use interfaces and types that implement interfaces�察�you are writing ponent

           oriented software。 ponents and inheritance are two different object´oriented techniques。  

          You use inheritance to implement interfaces�察�but ponents serve the purpose of making  

           ideas happen。 



           Understanding How Inheritance and ponents Work 



           Inheritance is the act of defining base classes with functionality that may or may not be over

           ridden or overloaded�察�as explained in the previous chapter。 ponents define subsystems  

           that are put together like pieces of a puzzle。 The idea behind ponents is to be able to asso

           ciate two interface instances and make them work with each other without knowing what the  

           other does。 

                To get a feeling of the difference between inheritance using classes and ponents that  

           use interfaces and classes�察�we will look at a classic example of inheritance and how that example  

           translates to ponents。 



           Illustrating Inheritance Using a Shape�察�Rectangle�察�and Square 



           One of the most popular examples of using inheritance involves shapes and how to calculate  

           the area of a shape。 The starting point of this inheritance is a MustInherit base class that has a  

           single property and method to indicate a single dimension and its associated area。 For example�察 �

           the following would be an appropriate base class definition。 



           MustInherit Class Shape  

              Public MustOverride Function CalculateArea�┌� As Double 

           End Class  



                The method CalculateArea�┌� is used to calculate the area of the shape。 It is declared as  

           MustOverride and must be implemented by a derived class。 


´´´´´´´´´´´´´´´´´´´´´´Page 191´´´´´´´´´´´´´´´´´´´´´´´

                           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 169 



     For starters�察�let¨s define Square�察�which represents the square shape。 



Class Square  

    Inherits Shape 



    Private _width As Double 

    Public Property Width�┌� As Double 

        Get  

            Return _width 

        End Get 

        Set��ByVal value As Double�� 

            _width = value 

        End Set 

    End Property 



    Public Overrides Function CalculateArea�┌� As Double 

        Return Width * Width 

    End Function 

End Class 



     A square has only one dimension�察�Width�察�which represents the width of a particular shape。 In  

the case of a square�察�width means one of the four sides。 We¨ve implemented the CalculateArea�┌�  

method�察�which calculates the surface area of the square by multiplying the Width property  

by itself。 

     A rectangle is a form of square�察�and therefore  Rectangle derives from  Square�此�



Class Rectangle  

    Inherits Square 



    Private _length As Double 

    Public Property Length�┌� As Double 

        Get  

            Return _length 

        End Get 

        Set��ByVal value As Double��  

            _length = value 

        End Set 

    End Property 



    Public Overloads Function CalculateArea�┌� As Double 

        Return Width * Length 

    End Function 

End Class 



     Rectangle cannot be described using a single dimension�察�thus we need to add the property  

Length。 In the implementation of the Rectangle。CalculateArea�┌� method to calculate the area�察 �

the length is multiplied by the width。 

     Take a good look at how CalculateArea�┌� is declared。 In the case of Rectangle。 

CalculateArea�┌��察�the Overloads keyword is used�察�not Overrides。 This is because you want to  


´´´´´´´´´´´´´´´´´´´´´´Page 192´´´´´´´´´´´´´´´´´´´´´´´

170       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 



           enforce calculation consistency。 Calculation consistency is when you perform a specific calcula

           tion on a type and get the answer expected of that type�察�and not some other type。  

                So�察�say you instantiate Rectangle�察�and then cast it to Square。 When you call CalculateArea�┌��察 �

           you want it to calculate as if the rectangle were a square�察�not a rectangle。 Thus�察�by adding the  

           Overloads keyword in the  Rectangle。CalculateArea�┌� method�察�a square is calculated as a  

           square�察�and a rectangle is calculated as a rectangle。 

                But there is a consequence。 Let¨s say Rectangle is cast to Shape。 As the inheritance is declared  

           when calling CalculateArea�┌��察�the area of a square is calculated�察�which is not correct。 Thus it  

           would seem that using New is incorrect�察�and Overrides should be used instead。 So using Overrides  

           solves the Shape。CalculateArea�┌� problem�察�but when a rectangle is converted into a square�察 �

           the area represents a rectangle and not square。  

                To illustrate the differences�察�assuming the use of Overloads�察�look at the following source  

           code�察�which calculates the area of a Rectangle。 



           Dim cls As Rectangle = New Rectangle�┌� 

           cls。Width = 20 

           cls。Length = 30 

           Dim area As Double = cls。CalculateArea�┌� 



                In the example�察�Rectangle is instantiated�察�and the properties Width and  Length are assigned  

           values of 20 and 30�察�respectively。 When the CalculateArea�┌� method is called�察�the found area is  

           assigned to the variable area。  

                The source code does what we expect。 It instantiates a rectangle�察�assigns the rectangle  

           dimensions�察�and calculates the area of the rectangle。 But a Rectangle object can also be assigned to  

           a square variable。 Consider the following modified source code�此�



           Dim rectangle As Rectangle = New Rectangle�┌� 

           rectangle。Width = 20 

           rectangle。Length = 30 

           Dim square As Square = rectangle 

           Dim area As Double = square。CalculateArea�┌� 

           Console。WriteLine�─�Square Area is ; & square。CalculateArea�┌� & _ 

               ; Rectangle Area is ; & rectangle。CalculateArea�┌��� 



                In the example�察�the variable rectangle is of type Rectangle。 The dimensions of the rectangle  

           are assigned�察�and then the rectangle is converted into a square and assigned to the variable square。  

           Using the keyword Overloads�察�the area is 400�察�which is correct because when we ask for the  

           dimensions of the square�察�we get a width of 20。 

                The various techniques used in this example are explained in the remainder of this chapter。 



           *Note  The example illustrates that by using inheritance�察�you can cast a type and get the appropriate behavior。  

           But this works only if you design your inheritance hierarchy properly。 You need to understand that behavior  

           depends on the type that you have from the inheritance tree。 And if you are not careful�察�you can get some very  

           odd side effects。 Visual Basic allows you to explicitly define what each method does�察�and you should think  

           very hard about what each method should do。 


´´´´´´´´´´´´´´´´´´´´´´Page 193´´´´´´´´´´´´´´´´´´´´´´´

                            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 171 



Illustrating ponents Using a Shape�察�Rectangle�察�and Square 



Another way to implement a shape is to use ponents。 Using ponents means to define  

an idea�察�and then define an implementation of the idea。 Designing and implementing po

nents is not similar to designing and implementing inheritance trees。 With inheritance�察�you  

need to consider type casting�察�base class functionality�察�and how to override or overload methods or  

properties。 �─�Type casting is when you cast to a specific type with or without an explicit cast  

operator。�� With ponents�察�you need to think in terms of ideas and how they would be imple

mented as interfaces。 

     Having looked at the Shape�察�Rectangle�察�and Square implementation�察�you might define an  

interface ��named IShape�� as follows�此�



Interface IShape  

    Function CalculateArea�┌� As Double 

    Property Width�┌� As Double 

End Interface 



     For the IShape declaration�察�you might even add a  Length property�察�but the overall idea of  

the IShape interface is wrong。 When you think of a shape�察�do you think in terms of length and  

width�拭�Probably not。 Rather�察�you think in terms of area�察�perimeter�察�and other features that are  

mon to all shapes。 Length and width are not mon to all shapes。 A circle has a radius or  

diameter�察�a triangle has base width�察�height�察�and triangle peak offset。 The point is that the idea  

of a shape is not the idea of a rectangle or a square。 

     The correct way to define the ideas as interfaces would be as follows�此�



Interface IShape  

    Function CalculateArea�┌� As Double 

End Interface 



Interface ISquare  

    Inherits IShape 

    Property Width�┌� As Double 

End Interface 



Interface IRectangle  

    Inherits IShape 

    Property Width�┌� As Double 

    Property Length�┌� As Double 

End Interface 



     This code contains three interfaces�此�IShape�察�which defines a shape�察�IRectangle�察�which  

describes a rectangle�察�and ISquare�察�which describes a square。 The IRectangle and ISquare  

interfaces subclass the IShape interface�察�indicating that an IRectangle is also an  IShape。 The  

ISquare interface is separate from the  IRectangle interface�察�because the idea of a square ��four  

equal sides�� is not the same as the idea of a rectangle ��only the parallel sides of the four sides  

must be equal���察�even though the shapes might appear similar ��in real life�察�a square is a rectangle�察 �

but a rectangle is not necessarily a square��。  

     This separation of the square and rectangle interface illustrates that when designing inter

faces�察�you need to focus on the specific behavior of the interface。 You don¨t want to focus on  


´´´´´´´´´´´´´´´´´´´´´´Page 194´´´´´´´´´´´´´´´´´´´´´´´

172       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 general behavior。 The general behavior is managed when you design the classes。 The modeling  

          of your real´life experiences is defined in the implementations�察�as illustrated by the following  

          example。 



          Class SquareImpl 

              Implements ISquare�察�IRectangle 

          End Class 



          Class RectangleImpl 

              Implements IRectangle 

          End Class 



               The SquareImpl class implements the behavior of ISquare and IRectangle�察�and models real life�察 �

          where a square is also a rectangle。 And RectangleImpl implements only the behavior IRectangle�察 �

          illustrating that a rectangle can only be a rectangle and not a square。 Now you cannot write  

          code where the implementation produces inconsistent results。  



          *Note  When defining ideas�察�the resulting interfaces could be considered as behavior characteristics that  

          an implementation can have。 It is entirely possible for an implementation to have multiple behavior character

          istics。 For example�察�this could mean that an implementation could be both a square and rectangle at the same  

          time。 In terms of the restaurant�察�waiters are humans with hobbies�察�feelings�察�and desires�察�although you don¨t  

          know these other aspects�察�as you see only the waiters。 



               An optimization could have been the following interface inheritance。 



          Interface ISquare  

              Inherits IShape 

              Property Width�┌� As Double 

          End Interface 



          Interface IRectangle 

              Inherits ISquare 

              Property Length�┌� As Double 

          End Interface 



          or 



          Interface ISquare  

              Inherits IRectangle 

          End Interface 



          Interface IRectangle 

              Inherits IShape 

              Property Width�┌� As Double 

              Property Length�┌� As Double 

          End Interface 


´´´´´´´´´´´´´´´´´´´´´´Page 195´´´´´´´´´´´´´´´´´´´´´´´

                           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 173 



     However�察�this isn¨t a good idea�察�because at the interface level�察�you are implying that a square  

and rectangle are related。 They might be at the implementation level�察�but they also might not  

be。 For example�察�imagine you are creating a super shape that has the characteristics of a rect

angle and a triangle。 When creating a relationship between interfaces�察�you are implying that  

the super shape depending on the interface inheritance used must have the characteristics of  

a square�察�even though it might not。 Thus�察�when using inheritance with interfaces�察�IShape as a  

base interface of IRectangle and ISquare is acceptable�察�but a relation between  IRectangle and  

ISquare is not。  

     Now that you have an idea of the differences between inheritance and ponents�察�we  

can get started with our tax application。 As we work through the example�察�you¨ll learn the  

details of implementing interfaces。 



Implementing a Tax Engine 



So far�察�we¨ve discussed some basic tax concepts�察�the features of the tax application�察�and the  

theory of inheritance�察�interfaces�察�and ponents。 We¨re ready to implement the tax engine。  

The preferred approach is to design the core idea and then create the other pieces�察�or  

dependencies。 



Defining the Interfaces 



Putting everything together and starting with the tax engine�察�we can create the following  

interface structure。 



Public Interface ITaxIne  

    ReadOnly Property RealAmount�┌� As Double 

    ReadOnly Property TaxableAmount�┌� As Double 

End Interface 



Public Interface ITaxDeduction  

    ReadOnly Property Amount�┌� As Double 

End Interface 



Public Interface ITaxAccount  

    Sub AddDeduction��ByVal deduction As ITaxDeduction�� 

    Sub AddIne��ByVal ine As ITaxIne�� 

    Function GetTaxRate��ByVal ine As Double�� As Double 

    ReadOnly Property Deductions�┌� As ITaxDeduction�┌� 

    ReadOnly Property Ine�┌� As ITaxIne�┌� 

End Interface 



Public Interface ITaxEngine  

    Function CalculateTaxToPay��ByVal account As ITaxAccount�� As Double 

    Function CreateDeduction��ByVal amount As Double�� As ITaxDeduction 

    Function CreateIne��ByVal amount As Double�� As ITaxIne 

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