
- •Using Your Sybex Electronic Book
- •Acknowledgments
- •Contents at a Glance
- •Introduction
- •Who Should Read This Book?
- •How About the Advanced Topics?
- •The Structure of the Book
- •How to Reach the Author
- •The Integrated Development Environment
- •The Start Page
- •Project Types
- •Your First VB Application
- •Making the Application More Robust
- •Making the Application More User-Friendly
- •The IDE Components
- •The IDE Menu
- •The Toolbox Window
- •The Solution Explorer
- •The Properties Window
- •The Output Window
- •The Command Window
- •The Task List Window
- •Environment Options
- •A Few Common Properties
- •A Few Common Events
- •A Few Common Methods
- •Building a Console Application
- •Summary
- •Building a Loan Calculator
- •How the Loan Application Works
- •Designing the User Interface
- •Programming the Loan Application
- •Validating the Data
- •Building a Math Calculator
- •Designing the User Interface
- •Programming the MathCalculator App
- •Adding More Features
- •Exception Handling
- •Taking the LoanCalculator to the Web
- •Working with Multiple Forms
- •Working with Multiple Projects
- •Executable Files
- •Distributing an Application
- •VB.NET at Work: Creating a Windows Installer
- •Finishing the Windows Installer
- •Running the Windows Installer
- •Verifying the Installation
- •Summary
- •Variables
- •Declaring Variables
- •Types of Variables
- •Converting Variable Types
- •User-Defined Data Types
- •Examining Variable Types
- •Why Declare Variables?
- •A Variable’s Scope
- •The Lifetime of a Variable
- •Constants
- •Arrays
- •Declaring Arrays
- •Initializing Arrays
- •Array Limits
- •Multidimensional Arrays
- •Dynamic Arrays
- •Arrays of Arrays
- •Variables as Objects
- •So, What’s an Object?
- •Formatting Numbers
- •Formatting Dates
- •Flow-Control Statements
- •Test Structures
- •Loop Structures
- •Nested Control Structures
- •The Exit Statement
- •Summary
- •Modular Coding
- •Subroutines
- •Functions
- •Arguments
- •Argument-Passing Mechanisms
- •Event-Handler Arguments
- •Passing an Unknown Number of Arguments
- •Named Arguments
- •More Types of Function Return Values
- •Overloading Functions
- •Summary
- •The Appearance of Forms
- •Properties of the Form Control
- •Placing Controls on Forms
- •Setting the TabOrder
- •VB.NET at Work: The Contacts Project
- •Anchoring and Docking
- •Loading and Showing Forms
- •The Startup Form
- •Controlling One Form from within Another
- •Forms vs. Dialog Boxes
- •VB.NET at Work: The MultipleForms Project
- •Designing Menus
- •The Menu Editor
- •Manipulating Menus at Runtime
- •Building Dynamic Forms at Runtime
- •The Form.Controls Collection
- •VB.NET at Work: The DynamicForm Project
- •Creating Event Handlers at Runtime
- •Summary
- •The TextBox Control
- •Basic Properties
- •Text-Manipulation Properties
- •Text-Selection Properties
- •Text-Selection Methods
- •Undoing Edits
- •VB.NET at Work: The TextPad Project
- •Capturing Keystrokes
- •The ListBox, CheckedListBox, and ComboBox Controls
- •Basic Properties
- •The Items Collection
- •VB.NET at Work: The ListDemo Project
- •Searching
- •The ComboBox Control
- •The ScrollBar and TrackBar Controls
- •The ScrollBar Control
- •The TrackBar Control
- •Summary
- •The Common Dialog Controls
- •Using the Common Dialog Controls
- •The Color Dialog Box
- •The Font Dialog Box
- •The Open and Save As Dialog Boxes
- •The Print Dialog Box
- •The RichTextBox Control
- •The RTF Language
- •Methods
- •Advanced Editing Features
- •Cutting and Pasting
- •Searching in a RichTextBox Control
- •Formatting URLs
- •VB.NET at Work: The RTFPad Project
- •Summary
- •What Is a Class?
- •Building the Minimal Class
- •Adding Code to the Minimal Class
- •Property Procedures
- •Customizing Default Members
- •Custom Enumerations
- •Using the SimpleClass in Other Projects
- •Firing Events
- •Shared Properties
- •Parsing a Filename String
- •Reusing the StringTools Class
- •Encapsulation and Abstraction
- •Inheritance
- •Inheriting Existing Classes
- •Polymorphism
- •The Shape Class
- •Object Constructors and Destructors
- •Instance and Shared Methods
- •Who Can Inherit What?
- •Parent Class Keywords
- •Derived Class Keyword
- •Parent Class Member Keywords
- •Derived Class Member Keyword
- •MyBase and MyClass
- •Summary
- •On Designing Windows Controls
- •Enhancing Existing Controls
- •Building the FocusedTextBox Control
- •Building Compound Controls
- •VB.NET at Work: The ColorEdit Control
- •VB.NET at Work: The Label3D Control
- •Raising Events
- •Using the Custom Control in Other Projects
- •VB.NET at Work: The Alarm Control
- •Designing Irregularly Shaped Controls
- •Designing Owner-Drawn Menus
- •Designing Owner-Drawn ListBox Controls
- •Using ActiveX Controls
- •Summary
- •Programming Word
- •Objects That Represent Text
- •The Documents Collection and the Document Object
- •Spell-Checking Documents
- •Programming Excel
- •The Worksheets Collection and the Worksheet Object
- •The Range Object
- •Using Excel as a Math Parser
- •Programming Outlook
- •Retrieving Information
- •Recursive Scanning of the Contacts Folder
- •Summary
- •Advanced Array Topics
- •Sorting Arrays
- •Searching Arrays
- •Other Array Operations
- •Array Limitations
- •The ArrayList Collection
- •Creating an ArrayList
- •Adding and Removing Items
- •The HashTable Collection
- •VB.NET at Work: The WordFrequencies Project
- •The SortedList Class
- •The IEnumerator and IComparer Interfaces
- •Enumerating Collections
- •Custom Sorting
- •Custom Sorting of a SortedList
- •The Serialization Class
- •Serializing Individual Objects
- •Serializing a Collection
- •Deserializing Objects
- •Summary
- •Handling Strings and Characters
- •The Char Class
- •The String Class
- •The StringBuilder Class
- •VB.NET at Work: The StringReversal Project
- •VB.NET at Work: The CountWords Project
- •Handling Dates
- •The DateTime Class
- •The TimeSpan Class
- •VB.NET at Work: Timing Operations
- •Summary
- •Accessing Folders and Files
- •The Directory Class
- •The File Class
- •The DirectoryInfo Class
- •The FileInfo Class
- •The Path Class
- •VB.NET at Work: The CustomExplorer Project
- •Accessing Files
- •The FileStream Object
- •The StreamWriter Object
- •The StreamReader Object
- •Sending Data to a File
- •The BinaryWriter Object
- •The BinaryReader Object
- •VB.NET at Work: The RecordSave Project
- •The FileSystemWatcher Component
- •Properties
- •Events
- •VB.NET at Work: The FileSystemWatcher Project
- •Summary
- •Displaying Images
- •The Image Object
- •Exchanging Images through the Clipboard
- •Drawing with GDI+
- •The Basic Drawing Objects
- •Drawing Shapes
- •Drawing Methods
- •Gradients
- •Coordinate Transformations
- •Specifying Transformations
- •VB.NET at Work: Plotting Functions
- •Bitmaps
- •Specifying Colors
- •Defining Colors
- •Processing Bitmaps
- •Summary
- •The Printing Objects
- •PrintDocument
- •PrintDialog
- •PageSetupDialog
- •PrintPreviewDialog
- •PrintPreviewControl
- •Printer and Page Properties
- •Page Geometry
- •Printing Examples
- •Printing Tabular Data
- •Printing Plain Text
- •Printing Bitmaps
- •Using the PrintPreviewControl
- •Summary
- •Examining the Advanced Controls
- •How Tree Structures Work
- •The ImageList Control
- •The TreeView Control
- •Adding New Items at Design Time
- •Adding New Items at Runtime
- •Assigning Images to Nodes
- •Scanning the TreeView Control
- •The ListView Control
- •The Columns Collection
- •The ListItem Object
- •The Items Collection
- •The SubItems Collection
- •Summary
- •Types of Errors
- •Design-Time Errors
- •Runtime Errors
- •Logic Errors
- •Exceptions and Structured Exception Handling
- •Studying an Exception
- •Getting a Handle on this Exception
- •Finally (!)
- •Customizing Exception Handling
- •Throwing Your Own Exceptions
- •Debugging
- •Breakpoints
- •Stepping Through
- •The Local and Watch Windows
- •Summary
- •Basic Concepts
- •Recursion in Real Life
- •A Simple Example
- •Recursion by Mistake
- •Scanning Folders Recursively
- •Describing a Recursive Procedure
- •Translating the Description to Code
- •The Stack Mechanism
- •Stack Defined
- •Recursive Programming and the Stack
- •Passing Arguments through the Stack
- •Special Issues in Recursive Programming
- •Knowing When to Use Recursive Programming
- •Summary
- •MDI Applications: The Basics
- •Building an MDI Application
- •Built-In Capabilities of MDI Applications
- •Accessing Child Forms
- •Ending an MDI Application
- •A Scrollable PictureBox
- •Summary
- •What Is a Database?
- •Relational Databases
- •Exploring the Northwind Database
- •Exploring the Pubs Database
- •Understanding Relations
- •The Server Explorer
- •Working with Tables
- •Relationships, Indices, and Constraints
- •Structured Query Language
- •Executing SQL Statements
- •Selection Queries
- •Calculated Fields
- •SQL Joins
- •Action Queries
- •The Query Builder
- •The Query Builder Interface
- •SQL at Work: Calculating Sums
- •SQL at Work: Counting Rows
- •Limiting the Selection
- •Parameterized Queries
- •Calculated Columns
- •Specifying Left, Right, and Inner Joins
- •Stored Procedures
- •Summary
- •How About XML?
- •Creating a DataSet
- •The DataGrid Control
- •Data Binding
- •VB.NET at Work: The ViewEditCustomers Project
- •Binding Complex Controls
- •Programming the DataAdapter Object
- •The Command Objects
- •The Command and DataReader Objects
- •VB.NET at Work: The DataReader Project
- •VB.NET at Work: The StoredProcedure Project
- •Summary
- •The Structure of a DataSet
- •Navigating the Tables of a DataSet
- •Updating DataSets
- •The DataForm Wizard
- •Handling Identity Fields
- •Transactions
- •Performing Update Operations
- •Updating Tables Manually
- •Building and Using Custom DataSets
- •Summary
- •An HTML Primer
- •HTML Code Elements
- •Server-Client Interaction
- •The Structure of HTML Documents
- •URLs and Hyperlinks
- •The Basic HTML Tags
- •Inserting Graphics
- •Tables
- •Forms and Controls
- •Processing Requests on the Server
- •Building a Web Application
- •Interacting with a Web Application
- •Maintaining State
- •The Web Controls
- •The ASP.NET Objects
- •The Page Object
- •The Response Object
- •The Request Object
- •The Server Object
- •Using Cookies
- •Handling Multiple Forms in Web Applications
- •Summary
- •The Data-Bound Web Controls
- •Simple Data Binding
- •Binding to DataSets
- •Is It a Grid, or a Table?
- •Getting Orders on the Web
- •The Forms of the ProductSearch Application
- •Paging Large DataSets
- •Customizing the Appearance of the DataGrid Control
- •Programming the Select Button
- •Summary
- •How to Serve the Web
- •Building a Web Service
- •Consuming the Web Service
- •Maintaining State in Web Services
- •A Data-Driven Web Service
- •Consuming the Products Web Service in VB
- •Summary

POLYMORPHISM 373
Polymorphism
This is another powerful aspect of inheritance. Polymorphism is the ability of a base type to adjust itself to accommodate many different derived types. Let’s make it simpler by using some analogies in the English language. Take the word run, for example. This verb can be used to describe athletes, cars, or refrigerators; they all “run.” In different sentences, the same word takes different meanings. When you use it with a person, it means going a distance at a fast pace. When you use it with a refrigerator, it means that it’s working. When you use it with a car, it may take on both meanings. So, in a sense the word run is polymorphic (and so are many other English words): Its exact meaning is differentiated according to the context.
To apply the same analogy to computers, think of a class that describes a basic object, like a Shape. This class would be very complicated if it had to describe and handle all shapes. It would be incomplete too, because the moment you released it to the world, you’d think of a new shape that can’t be described by your class. To design a class that describes all shapes, you build a very simple class to describe shapes at large, and then you build a separate class for each individual shape: a Triangle class, a Square class, a Circle class, and so on. As you can guess, all these classes inherit the Shape class. Let’s also assume that all the classes that describe individual shapes expose an Area method, which calculates the area of the shape they describe. The name of the Area method is the same for all classes, but it calculates a different formula.
The developer, however, doesn’t have to learn a different syntax of the Area method for each shape. They can declare a Square object and calculate its area with the following statements:
Dim shape1 As New Square, area As Double area = shape1.Area
If shape2 represents a circle, the same method will calculate the circle’s area:
Dim shape2 As New Circle, area As Double area = shape2.Area
You can go through a list of objects derived from the Shape class and calculate their areas by calling the Area method. No need to know what shape each object represents—you just call its Area method. Let’s say you’ve created an ArrayList with various shapes. You can go through the collection and calculate the total area with a loop like the following:
Dim shapeEnum As IEnumerator Dim totalArea As Double shapeEnum = aList.GetEnumerator While shapeEnum.MoveNext
totalArea = totalArea + CType(shapeEnum.Current, Shape).area End While
The CType() function converts the current element of the collection to a Shape object; it’s necessary only if the Strict option is on, which prohibits VB from late-binding the expression (Strict is off by default). As a reminder, when the Strict option is off, trivial mistakes will manifest themselves as runtime exceptions. If you mistype the name of the Area method as Arae, the compiler won’t catch this error at design time. If the Strict option is on, however, the error will be caught as you type.
The Area method is polymorphic. Its exact meaning (or formula, in the case of shapes) is adjusted to the context in which it’s used. OK, this is a simple concept. It’s only natural that we’re
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |

374 Chapter 8 BUILDING CUSTOM CLASSES
able to call the Area method to calculate the area of any shape, isn’t it? Believe me, it took us many years to get there. VB.NET is the first version of VB that supports true polymorphism. We’re going to look at the implementation of the classes that describe shapes in a moment, but first I would like to discuss some alternatives and show you the drawbacks, so that you won’t think that building classes to calculate the areas of various shapes is wasted time.
The first alternative would be to build a separate function to calculate the area of each shape (SquareArea, CircleArea, and so on). It will work, but why bother with so many function names, not to mention the overhead in your code? You must first figure out the type of shape described by a specific variable, like shape1, and then call the appropriate method. The code will not be as easy to read, and the longer the application gets, the more If and Case statements you’ll be coding.
The second, even less efficient method is a really long Area() function that would be able to calculate the area of all shapes. This function should be a very long Case statement, like the following one:
Public Function Area(ByVal shapeType As String) As Double Select Case shapeType
Case “Square”: { calculate the area of a square } Case “Circle”: { calculate the area of a circle } { . . . more Case statements }
End Select End Function
The real problem with this approach is that every time you want to add a new segment to calculate the area of a new shape to the function, you’d have to edit it. If another developer wanted to add a shape, they’d be out of luck.
In the following section, we’ll build the Shape class, which we’ll extend with individual classes for various shapes. You’ll be able to add your own classes to implement additional shapes, and any code written using the older versions of the Shape class will keep working.
The Shape Class
Let’s start with the Shape class, which will be the base class for all other shapes. This is a really simple class that’s pretty useless on its own. Its real use is that it exposes some members that can be inherited. The base class exposes two methods, Area and Perimeter. Even the two methods don’t do much—actually, they do absolutely nothing. All they really do is provide a naming convention. All classes that will inherit the Shape class will have an Area and a Perimeter method. They must provide the implementation of these methods, so that all object variables that represent shapes will expose an Area method and a Perimeter method.
Start a new project as usual, add a Shape class, and enter the code of Listing 8.37 in it.
Listing 8.37: The Shape Class
Class Shape
Overridable Function Area() As Double
End Function
Overridable Function Perimeter() As Double
End Function
End Class
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |

POLYMORPHISM 375
If there are properties common to all shapes, you place the appropriate Property procedures in the Shape class. If you want to assign a color to your shapes, place a Color property in this class. The Overridable keyword means that a class that inherits from the Shape class can override the default implementation of the corresponding methods or properties. As you will see shortly, it is possible for the base class to provide a few members that can’t be overridden in the derived class.
Then you can implement the classes for the individual shapes. Add another Class to the project, name it Shapes, and enter Listing 8.38’s code in it.
Listing 8.38: The Square, Triangle, and Circle Classes
Public Class Square
Inherits Shape
Private sSide As Double
Public Property Side() As Double Get
Side = sSide End Get
Set
sSide = Value End Set
End Property
Public Overrides Function Area() As Double Area = sSide * sSide
End Function
Public Overrides Function Perimeter() As Double Return (4 * sSide)
End Function End Class
Public Class Triangle
Inherits Shape
Private side1, side2, side3 As Double Property SideA() As Double
Get
SideA = side1 End Get
Set
side1 = Value End Set
End Property
Property SideB() As Double Get
SideB = side2 End Get
Set
side2 = Value End Set
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |

376 Chapter 8 BUILDING CUSTOM CLASSES
End Property
Public Property SideC() As Double
Get
SideC = side3
End Get
Set
side3 = Value
End Set
End Property
Public Overrides Function Area() As Double
Dim perim As Double
perim = Perimeter()
Return (Math.Sqrt(perim * (perim - side1) * (perim - side2) * _
(perim - side3)))
End Function
Public Overrides Function Perimeter() As Double
Return (side1 + side2 + side3)
End Function
End Class
Public Class Circle
Inherits Shape
Private cRadius As Double
Public Property Radius() As Double
Get
Radius = cRadius
End Get
Set
cRadius = Value
End Set
End Property
Public Overrides Function Area() As Double
Return (Math.Pi * cRadius ^ 2)
End Function
Public Overrides Function Perimeter() As Double
Return (2 * Math.Pi * cRadius)
End Function
End Class
The Shapes.vb file contains three classes: Square, Triangle, and Circle. All three expose their basic geometric characteristics as properties. The Triangle class, for example, exposes the properties SideA, SideB, and SideC, which allow you to set the three sides of the triangle. In addition, all three classes expose the Area and Perimeter methods. These methods are implemented differently for each class, but they do the same thing: they return the area and the perimeter of the corresponding shape. The Area method of the Triangle class is a bit involved, but it’s just a formula.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |

POLYMORPHISM 377
Testing the Shape Class
To test the Shapes class, all you have to do is create three variables—one of each type of shape—and call their methods. Or, you can store all three variables into an array and iterate through them. If the collection contains Shape variables only, the current item is always a shape, and as such it exposes the Area and Perimeter methods. The code in Listing 8.39 does exactly that. First, it declares three variables of the Triangle, Circle, and Square types. Then it sets their properties and calls their Area method to print their areas.
Listing 8.39: Testing the Shape Class
Protected Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs)
Dim shape1 As New Triangle()
Dim shape2 As New Circle()
Dim shape3 As New Square()
‘Set up a triangle shape1.SideA = 3 shape1.SideB = 3.2 shape1.SideC = 0.94
Console.WriteLine(“The triangle’s area is “ & shape1.Area.ToString)
‘Set up a circle
shape2.Radius = 4
Console.WriteLine(“The circle’s area is “ & shape2.Area.ToString)
‘Set up a square shape3.Side = 10.01
Console.WriteLine(“The square’s area is “ & shape3.Area.ToString) Dim shapes() As Shape
shapes(0) = shape1 shapes(1) = shape2 shapes(2) = shape3
Dim shapeEnum As IEnumerator Dim totalArea As Double shapeEnum = shapes.GetEnumerator
While shapeEnum.MoveNext
totalArea = totalArea + CType(shapeEnum.Current, shape).Area End While
Console.WriteLine(“The total area of your shapes is “ & totalArea.ToString) End Sub
In the last section, the test code stores all three variables into an array and iterates through its elements. At each iteration, it casts the current item to the Shape type and calls its Area method. The expression that calculates areas is CType(shapeEnum.Current, shape).Area, and the same expression calculates the area of any shape.
The Shape base class is quite trivial—it doesn’t expose any functionality of its own. Depending on how you will use the individual shapes in your application, you can add properties and methods
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |