友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
VB2008从入门到精通(PDF格式英文版)-第30部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
ExchangeRate = 100。0
End Sub
End Class
Protected scope means only those classes that derive from a class (and the class itself) can
view the methods; properties; or data members。 How many times and levels a class subclasses
another class is not important。
Public scope is the loosest and simplest of all scopes。 You use Public whenever you want
to expose functionality that other classes or derived classes want to reference。
Here are some guidelines for using each scope:
Private scope: You will use Private for most data member declarations because data member
declarations imply the state of an object。 Sometimes; when developing algorithms; you will
break apart the logic into several methods。 The broken…apart methods are used to solve a
problem; and thus should be used only in the context of the class; implying the methods
need to be declared using Private。
Protected scope: You will use Protected whenever you want to enforce an inheritance
architecture。 Very often; Protected and MustInherit go hand in hand; as both are intended
for inheritance。 The main objective behind Protected is to offer a derived class access to
the private state of a parent class; or to offer reusable functionality that should be used
only by knowledgeable developers who are creating the subclasses。
…………………………………………………………Page 170……………………………………………………………
148 CH AP T E R 6 ■ L E A R N IN G T HE B AS IC S O F OB J E CT OR I E N T E D P R O G R AM M IN G
Public scope: As a rule; think carefully before using Public。 You will use public scope for the
most part; but it is also the scope that can cause the most problems。 For example; once you
declare something as Public; trying to later change the scope could wreak havoc in the
code that uses the class。 It might be harder to develop using the other scopes; but you will
have code that will have fewer maintenance issues。 It all es down to which methods
and properties you want to expose to the outside world。
Handling Verification
To run the test class TestCurrencyTrader; the following code is used。
Dim cls As TestCurrencyTrader = New TestCurrencyTrader()
cls。InitializeExchangeRate()
The modified test code entails instantiating TestCurrencyTrader and then calling the method
InitializeExchangeRate()。 But is this a test? After all; the InitializeExchangeRate() method
doesn’t have a parameter or return value。 Think of it as sending a letter via mail。 You don’t
know if the letter will arrive; but it probably will。 Tests that are probably passed are a really
bad idea。
We need to move the verification code from the test routine to the TestCurrencyTrader
class; like this:
Class TestCurrencyTrader
Inherits CurrencyTrader
Public Sub InitializeExchangeRate()
ExchangeRate = 100。0
If ExchangeRate 100。0 Then
Throw New Exception(〃100。0 verification failed〃)
End If
End Sub
End Class
The bolded code illustrates the verification code used to ensure that the value assigned to
ExchangeRate is the same one that is retrieved。
■Note The tests we’re using are being more plicated; and you may wonder; “Why do it that way?”
For this book; we are writing tests and creating our own testing framework。 Normally you would not do that。
You would use a testing framework such as NUnit ( http://nunit。org) or the Microsoft Visual Studio
Professional tools to help create the tests。 But here I want to demonstrate how to use Visual Basic; not a
testing tool。 By learning how to write the tests from the ground up; you will understand what to expect from
testing frameworks。
Using Conditional Statements
Having verification code within a class is acceptable in the context of the test class
TestCurrencyTrader。 However; the problem of testability is still present in those classes that do
not expose their state。
…………………………………………………………Page 171……………………………………………………………
CH A PT E R 6 ■ L E A R N I N G T HE B AS IC S O F O B J E CT OR I E N TE D P R O G R AM M IN G 149
To understand the problem; let’s return to the code for preheating the oven that you saw
earlier in the section about the problems with properties。 Imagine rewriting Oven to include a
verification test; like this:
Class Oven
Private _temperature As Integer
Public Sub SetTemperature(ByVal temperature As Integer)
_temperature = temperature
If _temperature 100。0 Then
Throw New Exception(〃100。0 verification failed〃)
End If
End Sub
Public Function AreYouPreHeated() As Boolean
' Check if oven temperature matches prescribed temperature
Return False
End Function
End Class
The bolded code illustrates a verification much like that used in CurrencyTrader; which
verifies the parameter temperature for a specific value。 While the verification is useful for a
particular test; it is not useful in the big picture。 As the code is written; the only valid value of
temperature is 100。0; anything else will generate an exception。 It is definitely not a solution。
To get around this problem; you could use Visual Basic conditional statements。 Condi
tional statements are special keywords that allow a developer to define whether a piece of
source code is piled。 Following is an example of source code that includes conditional
statements。
Class TestCurrencyTrader
Inherits CurrencyTrader
Public Sub InitializeExchangeRate()
ExchangeRate = 100。0
#If INTEGRATE_TESTS Then
if ExchangeRate 100。0 Then
Throw New Exception(〃100。0 verification failed〃)
End If
#End If
End Sub
End Class
The conditional statement always starts with a hash character (#); immediately followed
by a keyword—If in this example。 Between the #If and #End If is code that is conditionally
piled。 This is known as a preprocessor directive。 In this example; the condition means
to pile the code contained within the #If and #End If block if the value INTEGRATE_TESTS
is true。
You can define a pilation identifier like INTEGRATE_TESTS in the source code or in your
IDE。 In Visual Basic Express; you can assign INTEGRATE_TESTS as follows:
…………………………………………………………Page 172……………………………………………………………
150 CH AP T E R 6 ■ L E A R N IN G T HE B AS IC S O F OB J E CT OR I E N T E D P R O G R AM M IN G
1。 Right…click your project and select Properties。
2。 Select the pile tab。
3。 Click the Advanced pile Options button。
4。 Add the INTEGRATE_TESTS value to the Custom Constants text box。
Using Partial Classes for Verification
Conditional pilation is useful when you want to include or remove code depending on a
configuration。 However; some programmers will frown upon having conditional pilation
code within a function; as that would be a maintenance nightmare。 Another solution is to use
the Partial class keyword in conjunction with conditional pilation statements。
Thus far in all of the examples; whenever we defined a class; all of the methods and code
were declared between the Class/End Class pair。 By using partial classes; it is possible to declare
a class in multiple places。 When the Visual Basic piler piles the source code; the individual
class pieces will be assembled into a single class definition。 For our test code; we can create an
implementation partial class and a conditionally piled test partial class implementation。
The following is the modified TestCurrencyTrader class that could be used to test the state
without exposing the state。
Partial Class TestCurrencyTrader
Inherits CurrencyTrader
Public Sub InitializeExchangeRate()
ExchangeRate = 100。0
End Sub
End Class
#if INTEGRATE_TESTS Then
Partial Class TestCurrencyTrader
Inherits CurrencyTrader
Public Sub VerifyExchangeRate(ByVal value As Double)
If ExchangeRate value Then
Throw New Exception(〃ExchangeRate verification failed〃)
End If
End Sub
End Class
#End If
The keyword Partial prefixes the Class keyword。 The first implementation of
TestCurrencyTrader is an example of not exposing state。 The second implementation of
TestCurrencyTrader; which is declared in the context of a conditional pilation statement;
contains the method VerifyExchangeRate()。 This is a verification method that tests the
ExchangeRate property for a particular value。
…………………………………………………………Page 173……………………………………………………………
CH A PT E R 6 ■ L E A R N I N G T HE B AS IC S O F O B J E CT OR I E N TE D P R O G R AM M IN G 151
■Note You can use partial classes only in the context of a single assembly; as the Partial keyword cannot
be used across assembly boundaries。 When I say “single assembly;” I am referring to the piled pieces of
source code illustrated in Chapter 1。 In other words; if you define a partial class in a library; then all
pieces of the partial class need to be defined in the library。
Partial classes make it simple to separate functionality into various source code files。 This
example demonstrates using partial classes to manipulate internal state of a class without
violating the do…not…expose…internal…state rule。 Another use of partial classes is in the context
of code generators; where one source code file contains the custom code; and the other source
code file contains the generator code。
■Note Only one part of a partial class needs to be explicitly qualified as Partial。 The piler is smart
enough to realize that if it sees one part as Partial; then all the other parts must also be partial (even if they
aren’t explicitly qualified with the Partial keyword)。
Finishing the Base Class
The ExchangeRate property is one of the pieces of shared functionality。 Another piece of shared
functionality we want to implement is the calculation of the exchange rate。 We’ll do this with
ConvertValue() and ConvertValueInverse() methods; which convert a currency from one value
to another using multiplication or division。 The following shows the methods in the pleted
base class implementation of CurrencyTrader。
Public MustInherit Class CurrencyTrader
Private _exchangeRate As Double
Protected Property ExchangeRate() As Double
Get
Return _exchangeRate
End Get
Set (ByVal Value As Double)
_exchangeRate = Value
End Set
End Property
Protected Function ConvertValue(ByVal input As Double) As Double
Return _exchangeRate * input
End Function
Protected Function ConvertValueInverse(ByVal input As Double) As Double
Return input / _exchangeRate
End Function
End Class
…………………………………………………………Page 174……………………………………………………………
152 CH AP T E R 6 ■ L E A R N IN G T HE B AS IC S O F OB J E CT OR I E N T E D P R O G R AM M IN G
The bolded code highlights the methods that convert the currency from one unit to another。
Notice that there is no declaration of specific currency units; because the base class is a utility
class used to help us realize an active trader or hotel trader implementation。
■Note Base class functionality; even when appearing trivial; is defined to ensure consistency in implemen
tation。 Without consistency; you encounter the problem where one implementation does one thing and another
implementation does something pletely different。
This pletes our test code。 Now we will implement the active trader and hotel trader
ponents of the currency exchange application。
Writing the Active Trader and Hotel Trader
Currency Converters
With the TestCurrencyTrader test solution pleted; it’s time to turn our attention to the
CurrencyTrader solution。 As mentioned earlier; this consists of the active trader and hotel
trader currency converter ponents。 Here; you’ll see more clearly what it means to use
inheritance。
Implementing ActiveCurrencyTrader
The ActiveCurrencyTrader class implements the logic of the active currency trader。 To begin;
we’ll add its constructor。
Adding a Constructor to ActiveCurrencyTrader
To give ActiveCurrencyTrader some default state; we use a constructor。 However; the constructor
will serve another purpose; in that any class that instantiates ActiveCurrencyTrader will consider
the instance as immutable。 Immutable means that once data has been assigned to the instance; it
cannot be altered。 In other words; it is unchangeable。
■Note The String type is immutable because once a string variable has been assigned; it cannot be
changed。 Take a look at the methods associated with String; and you will see nothing that allows you to
modify the contents。 An immutable type is good because it allows you to implement a set…it…and…forget…it
object; and it prevents other classes from accidentally changing the contents。 Overall; an immutable type is
robust and predictable (though they are the exception; not the rule; most types allow you to modify state)。
The following shows the constructor code added to ActiveCurrencyTrader。
…………………………………………………………Page 175……………………………………………………………
CH A PT E R 6 ■ L E A R N I N G T HE B AS
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!