Section 11.2. Arrays of Objects


[Page 569 (continued)]

11.2. Arrays of Objects; Events; Containment

"An object without an event is like a telephone without a ringer."

Anonymous

Arrays of Objects

The elements of an array can have any data typeincluding a user-defined object. The program in Example 1 uses an array of type Student.

Example 1.
(This item is displayed on pages 569 - 571 in the print version)

In the following program, which uses the same form design as Example 1 of the previous section, the user enters four pieces of data about a student into text boxes. When the Enter Information button is pressed, the data are used to create and initialize an appropriate object and the object is added to an array. When the Display Grades button is pressed, the name, Social Security number, and semester grade for each student in the array are displayed in the list box.

 Public Class frmGrades   Dim students(50) As Student   Dim lastStudentAdded As Integer = -1     'Position in array of student                                           'most recently added   Private Sub btnEnter_Click(...) Handles btnEnter.Click     'Create an instance of student.     'Read the values stored in the text boxes.     Dim pupil As New Student()     pupil.Name = txtName.Text     pupil.SocSecNum = mtxtSSN.Text     pupil.MidGrade = CDbl(txtMidterm.Text)     pupil.Final = CDbl(txtFinal.Text)     'Add the student to the array     lastStudentAdded += 1     students(lastStudentAdded) = pupil     'Clear text boxes     txtName.Clear()     mtxtSSN.Clear()     txtMidterm.Clear()     txtFinal.Clear()     lstGrades.Items.Add("Student Recorded.")   End Sub   Private Sub btnDisplay_Click(...) Handles btnDisplay.Click     Dim fmtStr As String = "{0,-20}{1,-15}{2,-1}"     lstGrades.Items.Clear()     lstGrades.Items.Add(String.Format(fmtStr, "Student Name", _                                      "SSN", "Grade")) 
[Page 570]
For i As Integer = 0 To lastStudentAdded lstGrades.Items.Add(String.Format(fmtStr, students(i).Name, _ students(i).SocSecNum, students(i).CalcSemGrade)) Next End Sub Private Sub btnQuit_Click(...) Handles btnQuit.Click End End Sub End Class Class Student Private m_name As String Private m_ssn As String Private m_midterm As Double Private m_final As Double Public Property Name() As String Get Return m_name End Get Set(ByVal value As String) m_name = value End Set End Property Public Property SocSecNum() As String Get Return m_ssn End Get Set(ByVal value As String) m_ssn = value End Set End Property Public WriteOnly Property MidGrade() As Double Set(ByVal value As Double) m_midterm = value End Set End Property Public WriteOnly Property Final() As Double Set(ByVal value As Double) m_final = value End Set End Property Function CalcSemGrade() As String Dim grade As Double grade = (m_midterm + m_final) / 2 grade = Math.Round(grade) 'Round the grade.
[Page 571]
Select Case grade Case Is >= 90 Return "A" Case Is >= 80 Return "B" Case Is >= 70 Return "C" Case Is >= 60 Return "D" Case Else Return "F" End Select End Function End Class


[Run, type in data for Al Adams, press the Enter Information button, repeat the process for Brittany Brown and Carol Cole, press the Display Grades button, and then enter data for Daniel Doyle.]

Events

In the previous section, we drew a parallel between objects and controls and showed how to define properties and methods for classes. In addition to the predefined event New for classes, other events can be defined by the programmer to communicate changes of properties, errors, and the progress of lengthy operations. Such events are called user-defined events. The statement for triggering an event is located in the class block, and the event is dealt with in the form's code. Suppose that the event is named UserDefinedEvent and has the parameters par1, par2, and so on. In the class block, the statement

Public Event UserDefinedEvent(ByVal par1 As DataType1, _                             ByVal par2 As DataType2, ...)


should be placed in the Declarations section, and the statement

RaiseEvent UserDefinedEvent(arg1, arg2, ...)



[Page 572]

should be placed at the locations in the class block code at which the event should be triggered. In the form's code, an instance of the class, call it object1, must be declared with a statement of the type

Dim WithEvents object1 As ClassName


or the type

Dim WithEvents object1 As New ClassName


in order to be able to respond to the event. That is, the keyword WithEvents must be inserted into the declaration. The header of an event procedure for object1 will be

Private Sub object1_UserDefinedEvent(par1, par2, ...) _         Handles object1.UserDefinedEvent


Example 2.
(This item is displayed on pages 572 - 574 in the print version)

Consider the circle class defined in Example 3 of Section 11.1. In the following program, we add a user-defined event that is triggered whenever the location of a circle changes. The event has parameters to pass the location and diameter of the circle. The form's code uses the event to determine if part (or all) of the drawn circle will fall outside the picture box. If so, the event procedure displays the message "Circle Off Screen" in a text box. Let's call the event PositionChanged.

Object

Property

Setting

frmCircle

Text

Moving Circle

btnMove

Text

Move and Show Circle

btnQuit

Text

Quit

txtCaution

ReadOnly

True

picCircle

  


 Public Class frmCircle   Dim WithEvents round As New Circle()   Private Sub btnMove_Click(...) Handles btnMove.Click     round.Move(20)   End Sub   Private Sub btnQuit_Click(...) Handles btnQuit.Click     End   End Sub 
[Page 573]
Private Sub
round_PositionChanged(ByVal x As Integer, _ ByVal y As Integer, ByVal d As Integer) Handles round.PositionChanged 'This event is triggered when the location of the circle changes. 'The code determines if part of the circle is off the screen. If (x + d > picCircle.Width) Or _ (y + d > picCircle.Height) Then txtCaution.Text = "Circle Off Screen" End If round.Show(picCircle.CreateGraphics) End Sub End Class Class Circle Private m_x As Integer 'Dist from left side of picture box to circle Private m_y As Integer 'Distance from top of picture box to circle Private m_d As Integer 'Diameter of circle Public Event PositionChanged(ByVal x As Integer, _ ByVal y As Integer, ByVal d As Integer) 'Event is triggered when the circle moves. Public Sub New() 'Set the initial location of the circle to the upper-left 'corner of the picture box, and set its diameter to 40. Xcoord = 0 Ycoord = 0 Diameter = 40 End Sub Public Property Xcoord() As Integer Get Return m_x End Get Set(ByVal value As Integer) m_x = value End Set End Property Public Property Ycoord() As Integer Get Return m_y End Get Set(ByVal value As Integer) m_y = value End Set End Property
[Page 574]
Public Property
Diameter() As Integer Get Return m_d End Get Set(ByVal value As Integer) m_d = value End Set End Property Sub Show(ByRef g As Graphics) 'Draw a circle with the given graphics context. g.DrawEllipse(Pens.Black, Xcoord, Ycoord, Diameter, Diameter) End Sub Sub Move(ByVal distance As Integer) Xcoord += distance Ycoord += distance RaiseEvent PositionChanged(Xcoord, Ycoord, Diameter) End Sub End Class


[Run, and press the "Move and Show Circle" button eleven times.]

Note: As the last circle appears, the words "Circle Off Screen" are displayed in the text box.

Containment

We say that class A contains class B when a member variable of class A makes use of an object of type class B. In Example 3, the class DeckOfCards contains the class Card.

Example 3.
(This item is displayed on pages 574 - 578 in the print version)

The following program deals a five-card poker hand. The program has a deck-of-cards object containing an array of 52 card objects. The card object has two properties, Denomination and Suit, and one method, IdentifyCard. The IdentifyCard method returns a string such as "Ace of Spades." In the DeckOfCards object, the New event procedure assigns denominations and suits to the 52 cards. The method ReadCard(n) returns the string identifying the nth card of the deck. The method ShuffleDeck uses the Random class to mix up the cards while making 2000 passes through the deck. The event


[Page 575]

Shuffling(n As Integer, nMax As Integer)


is triggered during each shuffling pass through the deck, and its parameters communicate the number of the pass and the total number of passes, so that the program that uses it can keep track of the progress.

Object

Property

Setting

frmPoker

Text

Poker Hand

lstHand

  

btnShuffle

Text

&Shuffle

btnDeal

Text

&Deal

btnQuit

Text

&Quit


 Public Class frmPoker   Dim WithEvents cards As New DeckOfCards()   Private Sub btnShuffle_Click(...) Handles btnShuffle.Click     cards.ShuffleDeck   End Sub   Private Sub btnDeal_Click(...) Handles btnDeal.Click     Dim str As String     lstHand.Items.Clear()     For i As Integer = 0 To 4       str = cards.ReadCard(i)       lstHand.Items.Add(str)     Next   End Sub   Private Sub Quit_Click(...) Handles Quit.Click     End   End Sub   Private Sub cards_Shuffling(ByVal n As Integer, _                       ByVal nMax As Integer) Handles cards.Shuffling     'n is the number of the specific pass through the deck (1, 2, 3...).     'nMax is the total number of passes when the deck is shuffled.     lstHand.Items.Clear()     lstHand.Items.Add("Shuffling Pass: " & n & " out of " & nMax)     For i As Integer = 1 To 1000000     'Slow down the shuffle.     Next     lstHand.Update()  'Refresh contents of list box   End Sub End Class 
[Page 576]
Class
Card Private m_denomination As Integer 'A number from 0 through 12 Private m_suit As String 'Hearts, Clubs, Diamonds, Spades Public Property Denomination() As Integer Get Return m_denomination End Get Set(ByVal value As Integer) 'Only store valid values. If (value >= 0) And (value <= 12) Then m_denomination = value End If End Set End Property Public Property Suit() As String Get Return m_suit End Get Set(ByVal value As String) 'Only store valid values. If (value = "Hearts") Or (value = "Clubs") Or _ (value = "Diamonds") Or (value = "Spades") Then m_suit = value End If End Set End Property Function IdentifyCard() As String Dim denom As String = "" Select Case m_denomination + 1 Case 1 denom = "Ace" Case Is <= 10 denom = CStr(m_denomination + 1) Case 11 denom = "Jack" Case 12 denom = "Queen" Case 13 denom = "King" End Select Return denom & " of " & m_suit End Function End Class
[Page 577]
Class
DeckOfCards Private m_deck(51) As Card 'Class DeckOfCards contains class Card Public Event Shuffling(ByVal n As Integer, ByVal nMax As Integer) Public Sub New() 'Make the first thirteen cards hearts, the 'next thirteen cards diamonds, and so on. Dim suits() As String = {"Hearts", "Clubs", "Diamonds", "Spades"} For i As Integer = 0 To 3 'Each pass corresponds to one of the four suits. For j As Integer = 0 To 12 'Assign numbers from 0 through 12 to the 'cards of each suit. m_deck(i * 13 + j) = New Card() m_deck(i * 13 + j).Suit = suits(i) m_deck(i * 13 + j).Denomination = j Next Next End Sub Function ReadCard(ByVal cardNum As Integer) As String Return m_deck(cardNum).IdentifyCard() End Function Sub Swap(ByVal i As Integer, ByVal j As Integer) 'Swap the ith and jth card in the deck. Dim tempCard As Card tempCard = m_deck(i) m_deck(i) = m_deck(j) m_deck(j) = tempCard End Sub Sub ShuffleDeck() 'Do 2000 passes through the deck. On each pass, 'swap each card with a randomly selected card. Dim index As Integer Dim randomNum As New Random() For i As Integer = 1 To 2000 For k As Integer = 0 To 51 index = randomNum.Next(0, 52) 'Randomly select a number 'from 0 through 51 inclusive. Swap(k, index) Next RaiseEvent Shuffling(i, 2000) Next End Sub End Class



[Page 578]

[Run, click on the Shuffle button, and click on the Deal button after the shuffling is complete.]

Practice Problems 11.2

Consider the program in Example 1, and suppose that mtxtSSN is an ordinary text box.

1.

Alter the Set SocSecNum property procedure to raise the event ImproperSSN when the Social Security number does not have 11 characters. The event should pass the length of the Social Security number and the student's name to the form's code.

2.

What statement must be placed in the Declarations section of the class block?

3.

Write an event procedure for the event ImproperSSN.

4.

What statement in the form's code must be altered?

Exercises 11.2

1.

In Example 1, modify the event procedure btnDisplay_Click so that only the students who receive a grade of A are displayed.

The file STATES.TXT provides data on the 50 states. (This file is used in Exercises 2 through 5.) Each record contains five pieces of information about a single state: name, abbreviation, date it entered the union, land area (in square miles), and population in the year 2000. The records are ordered by the date of entry into the union. The first five lines of the file are

Delaware DE Dec. 1787 1954 759000


2.

Create (a) a class State with five properties to hold the information about a single state and (b) a method that calculates the density (people per square mile) of the state.

3.

Write a program that requests a state's name in an input dialog box and displays the state's abbreviation, density, and date of entrance into the union. The program should use an array of State objects.


[Page 579]
4.

Write a program that displays the names of the states and their densities in a list box ordered by density. The program should use an array of State objects.

5.

Write a program that reads the data from the file into an array of State objects and raises an event whenever the population of a state exceeds ten million. States with a large population should have their names and populations displayed in a list box by the corresponding event procedure. Hint: Create a class called UnitedStates that contains the array and defines a method Add that adds a new state to the array. The Add method should raise the event.

6.

Consider the class Square from Exercise 19 of Section 11.1 Add the event IllegalNumber that is raised when any of the properties is set to a negative number. Show the new class block and write an event procedure for the event that displays an error message.

7.

Consider the CashRegister class in Exercise 25 of Section 11.1. Add the event AttemptToOverdraw that is raised when the user tries to subtract more money than is in the cash register.

8.

Consider the class PairOfDice discussed in Exercise 21 of Section 11.1. Add the event SnakeEyes that is raised whenever two ones appear during a roll of the dice. Write a program that uses the event.

9.

Consider the Fraction class in Exercise 29 of Section 11.1. Add the event ZeroDenominator, that is triggered whenever a denominator is set to 0. Write a program that uses the event.

10.

Write a program for the fraction calculator shown in Figure 11.3. After the numerators and denominators of the two fractions to the left of the equals sign are placed in the four text boxes, one of four operations buttons should be pressed. The result appears to the right of the equals sign. The program should use a Calculator class, which contains three members of the type Fraction discussed in Exercise 29 of Section 11.1. Note: In Figure 11.3, the fraction bars are very short list boxes.

Figure 11.3. Sample Output for Exercise 10.


11.

Write a program that takes orders at a fast food restaurant. See Figure 11.4. The restaurant has two menus, a regular menu and a kids menu. An item is ordered by highlighting it in one of the list boxes and then pushing the >> or << button to place it in the order list box in the center of the form. As each item is ordered, a running total is displayed in the text box at the lower right part of the form. The program should use a Choices class, which contains a Food class. (The contents of each of the three list boxes should be treated as Choices objects.) Each Food object should hold the name and price of a single food item. Each Choices object should have a ChoiceChanged event that can be used by the form code to update the cost of the order.


[Page 580]

Figure 11.4. Sample Output for Exercise 11.


12.

Write a program for a simple game in which each of two players rolls a pair of dice. The person with the highest tally wins. See Figure 11.5. The program should use a Game class (HighRoller) having two member variables of the type PairOfDice discussed in Exercise 21 of Section 11.1.

Figure 11.5. Sample output for Exercise 12.


13.

Write a program to produce an employee's weekly paycheck receipt. The receipt should contain the employee's name, amount earned for the week, total amount earned for the year, FICA tax deduction, withholding tax deduction, and take-home amount. The program should use an Employee class and a Tax class. The Tax class must have properties for the amount earned for the week, the prior total amount earned for the year, the number of withholding exemptions, and marital status. It should have methods for computing FICA and withholding taxes. The Employee class should store the employee's name, number of withholding allowances, marital status, hours worked this week, hourly salary, and previous amount earned for the year. The Employee class should use the Tax class to calculate the taxes to be deducted. The formula for calculating the FICA tax is given in Exercise 28 of Section 11.1. To compute the withholding tax, multiply the number of withholding allowances by $61.54, subtract the product from the amount earned, and use Table 11.1 or Table 11.2.


[Page 581]

Table 11.1. 2005 Federal income tax withheld for a single person paid weekly.

Adjusted Weekly Income

Income Tax Withheld

$0 to $51

$0

Over $51 to $188

10% of amount over $51

Over $188 to $606

$13.70 + 15% of amount over $188

Over $606 to $1,341

$76.40 + 25% of amount over $606

Over $1,341 to $2,922

$260.15 + 28% of amount over $1,341

Over $2,922 to $6,313

$702.83 + 33% of amount over $2,922

Over $6,313

$1,821.86 + 35% of amount over $6,313


Table 11.2. 2005 Federal income tax withheld for a married person paid weekly.

Adjusted Weekly Income

Income Tax Withheld

$0 to $154

$0

Over $154 to $435

10% of amount over $154

Over $435 to $1,273

$28.10 + 15% of amount over $435

Over $1,273 to $2,322

$153.80 + 25% of amount over $1,273

Over $2,322 to $3,646

$416.05 + 28% of amount over $2,322

Over $3,646 to $6,409

$786.77 + 33% of amount over $3,646

Over $6,409

$1,698.56 + 35% of amount over $6,409


Solutions to Practice Problems 11.2

1.

Public Property SocSecNum() As String   Get     Return m_ssn   End Get   Set(ByVal value As String)     If value.Length = 11 Then       m_ssn = value     Else       RaiseEvent ImproperSSN(value.Length, m_name)     End If   End Set End Property


2.

Public Event ImproperSSN(ByVal length As Integer, _                        ByVal studentName As String)


3.

 Private Sub pupil_ImproperSSN(ByVal length As Integer, _             ByVal studentName As string) Handles pupil.ImproperSSN   MsgBox("The social security number entered for " & _         studentName & " consisted of " & length & _         " characters. Reenter the data for " & studentName & ".") End Sub



[Page 582]
4.

The statement

Dim pupil As New Student()


must be changed to

Dim WithEvents pupil As New Student()


and moved to the Declaration section.




An Introduction to Programming Using Visual Basic 2005
Introduction to Programming Using Visual Basic 2005, An (6th Edition)
ISBN: 0130306541
EAN: 2147483647
Year: 2006
Pages: 164

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net