按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
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 i