Inheritance versus Aggregation

When you derive a new class from an existing base class (that is, when you inherit), you get a copy of the members of the base class. We refer to this as an is-a relationship, as in "A Jeep is a car."

When a class contains another object, this is referred to as containment or aggregation . However, if you define members in the containing class that are implemented in terms of the contained class, you can make the containing class look a bit like and behave like the contained class. The aggregation relationship is referred to as a has-a relationship.

This promotion of members in a contained object is referred to in .NET vernacular as surfacing constituent object members . Technically, the aggregate can perform some of the same operations as a derived class but will not pass the is-a test. To perform type checking in Visual Basic .NET, use the TypeOf and Is operators. For example, if you want to determine the type of the sender argument passed to an event handler, you could write the following code.

 If(TypeOf sender Is Button) Then 

Choose inheritance when you want a derived type to be the same basic type as its parent and have the same members as the parent. Choose aggregation when you are defining a whole “part relationship; that is, the contained object is a part of the object that contains it. Also choose aggregation if you want to refine the interface of the contained object, for example, when a class has too many features or public members inappropriate for your needs. Wrap the existing class in a new class and surface only those constituent members that satisfy your new need.

The Adapter Pattern

Wrapping a class inside another class to change the contained class's interface is referred to as the Adapter pattern [Gamma et al. 1995]. Patterns reflect the names for problems, the solutions to those problems, and the consequences of applying the pattern. For example, when you need to change the interface of a class to get it to work with other classes in a system, this is the Adapter pattern too. Patterns are important because they solve challenging problems in a reliable way and prevent reinventing the wheel.

The study of patterns is beyond the scope of this book, but when I use a particular pattern to solve a problem I will indicate the name of the pattern. You can look up the pattern in a book on patterns, like the "Gang of Four" book referenced in the preceding paragraph, to explore the problem, solution, and consequences of that pattern.

The Adapter pattern generally uses multiple inheritance [Gamma et al. 1995]. Visual Basic .NET does not support multiple inheritance, but it does support single inheritance and aggregation; hence we can achieve the aims of using the Adapter pattern by combining inheritance and aggregation.

To demonstrate , let's take the shape classes defined earlier in this chapter and use an Adapter pattern, specifically a UserControl object, to make our shape classes work with a Windows Form.

Creating a UserControl Shape

A UserControl object is a container control derived from the Control class. UserControl objects are most often used to create business object controls; generally, UserControl objects contain many constituent controls to create a reusable piece of a solution.

For our purposes we are using a UserControl because it contains a drawing surface. (We need the drawing surface so we have something on which to render our shapes .) Listing 2.5 implements an enumeration and a UserControl . Based on the shape type represented by the enumeration, the UserControl will render a specific shape on the drawing surface. The complete solution is contained in Adapter.sln .

Listing 2.5 Creating a UserControl Object to Adapt Shape Classes to Work with a Windows Form
 1:  Public Enum ShapeType 2:    Ellipse 3:    Rectangle 4:    Circle 5:    FilledCircle 6:  End Enum 7: 8:  Public Class ShapeControl 9:    Inherits System.Windows.Forms.UserControl 10: 11: #Region " Windows Form Designer generated code " 12: 13:     Public Sub New() 14:         MyBase.New() 15: 16:         'This call is required by the Windows Form Designer. 17:         InitializeComponent() 18: 19:         Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True) 20:         BackColor = Color.Transparent 21:         ShapeType = ShapeType.Circle 22: 23:     End Sub 24: 25:     [Windows Form Designer generated code] 26: 27: #End Region 28: 29:   Private FShapeType As ShapeType 30:   Private FShape As Shape = Nothing 31: 32:   Public Property ShapeType() As ShapeType 33:   Get 34:     Return FShapeType 35:   End Get 36:   Set(ByVal Value As ShapeType) 37:     If (Value = FShapeType) Then Return 38:     FShapeType = Value 39:     Changed() 40:   End Set 41:   End Property 42: 43:   Private Function GetRect() As System.Drawing.Rectangle 44:     Return New System.Drawing.Rectangle(0, 0, Width - 1, Height - 1) 45:   End Function 46: 47:   Protected Sub Changed() 48:     FShape = New Shape() {New Ellipse(GetRect()), _ 49:       New Rectangle(GetRect()), New Circle(GetRect()), _ 50:       New FilledCircle(GetRect())}(FShapeType) 51: 52:     Invalidate() 53:   End Sub 54: 55:   Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs) 56:     MyBase.OnPaint(e) 57:     If (FShape Is Nothing) Then Exit Sub 58:     FShape.Draw(e.Graphics) 59:   End Sub 60: 61:   Protected Overrides Sub OnResize(ByVal e As System.EventArgs) 62:     MyBase.OnResize(e) 63:     Changed() 64:   End Sub 65: End Class 

The constructor on lines 13 to 23 sets the control style to support a transparent background; this will make the shape look like it is on the form rather than on the UserControl . The constructor also sets the default shape to be a circle and the background color to Color.Transparent . The enumeration on lines 1 to 6 support the various shape types.

Lines 32 to 41 define a ShapeType property. When a consumer changes the ShapeType property, the Shape object is created and the UserControl is invalidated, causing the shape to be updated. Lines 43 to 53 use an array and the enumerator to determine which shape object to create. The array is an array of shapes. Each element of the array is created dynamically and a specific shape is returned when the ShapeType property is used to index the array. (We could have used a Select Case statement to get the same result.)

The overridden OnPaint and OnResize methods ensure that the shape is painted when the UserControl is repainted or resized.

Visual Basic. NET Power Coding
Visual Basic(R) .NET Power Coding
ISBN: 0672324075
EAN: 2147483647
Year: 2005
Pages: 215
Authors: Paul Kimmel © 2008-2017.
If you may any questions please contact us: