Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 51 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
51
Dung lượng
849,51 KB
Nội dung
136 Chapter 5 Visual Basic 2005 data types, such as arrays, strings, and even integers, are actually full-featured objects. In Chapter 4 the plot thickened with forms, which were also exposed as a special type of object. As this book continues, you’ll learn how to create your own custom objects and use them for a variety of programming tasks. But before you can get there, you need a crash course in object-oriented programming. That’s where this chapter comes in. To make the best use of .NET objects, and to enhance your own applica- tions, you should develop a good understanding of object-oriented concepts. You may have already learned how to use classes and objects with a previous version of Visual Basic or another programming language. Even so, you’ll probably still want to read through the majority of this chapter and the next to explore the object-oriented features of VB 2005 and to get the big picture of the world of classes, interfaces, and object relationships. New in .NET Visual Basic 2005’s enhanced OOP features first appeared in .NET 1.0, when they were among the most hotly anticipated language changes. Visual Basic 2005 keeps all of these features (and adds a few more, which you’ll learn about in Chapter 6). At last, Visual Basic includes all the hallmarks of a true object- oriented language. In this chapter, you’ll see some of the following changes: The Class keyword In Visual Basic 6, each class required a separate file. Now you can group your classes any way you want, as long as you place all classes inside dec- larations (for example, start with Public Class MyClassName and end with End Class). The Is keyword In VB 2005, you test whether two objects are the same by using the Is keyword (for example, If objOne Is objTwo Then), not the equal sign. Constructors You can now use constructors to preload information into an object in a single line. Initializing objects can’t get any easier. Garbage collection Garbage collection replaces deterministic finalization. When you set an object to Nothing, it doesn’t disappear until the next time the garbage collector runs, which means that you can’t use an event handler to do the cleanup. Enumerations Need to use constants, but tired of using hard-coded numbers and strings? Enumerations give you the ability to define groups of related values and give each value a descriptive name, which makes for cleaner coding. bvb_02.book Page 136 Thursday, March 30, 2006 12:39 PM Object-Oriented Programming 137 Shared members The Shared keyword allows you to create properties, variables, and meth- ods that are always available, even when no instance object exists. Visual Basic 6 allowed you to create modules that were entirely made up of shared methods, but it didn’t provide anything close to the features and fine-grained control afforded by the Shared keyword. Introducing OOP Visual Basic is often accused of being a loosely structured language, and many VB developers lapse into an event-driven style of programming that scatters code fragments everywhere. If you want to write a program that has any chance of being extensible, reliable, and even fun to program, it’s up to you to adopt a more systematic programming methodology—and none is nearly as powerful, or as natural to the way Windows works, as object-oriented programming. It’s hard to imagine anything in the past ten years that has so completely caught the imagination of developers as object-oriented programming. What started off as an obscure philosophy for “language nerds” has grown into a whole assortment of nifty, easy-to-use techniques that can transform a com- plex, bloated application into a happy collection of intercommunicating objects. Quite simply, object-oriented programming makes it easier to debug, enhance, and reuse parts of an application. What’s more, object- oriented principles are the basis of core pieces of the Windows operating system—first with COM, and now with the .NET Framework. What Is Object-Oriented Programming? One of the more intimidating aspects of object-oriented programming is the way its advocates tout it as a philosophy (or even a religion). To keep things straight, it’s best to remind yourself that object-oriented programming really boils down to the best way to organize code. If you follow good object- oriented practices, you’ll end up with a program that’s easier to manage, enhance, and troubleshoot. But all these benefits are really the result of good organization. The Problems with Traditional Structured Programming Traditional structured programming divides a problem into two kinds of things: data and ways to process data. The problem with structured program- ming is that unless you’ve put a lot of forethought into your application design, you’ll quickly end up with a program that has its functionality scattered in many different places. bvb_02.book Page 137 Thursday, March 30, 2006 12:39 PM 138 Chapter 5 Consider a simple database program for sales tracking that includes a basic search feature. Quite probably, at some point, you’ll need to add the ability to search using slightly different criteria than you originally defined. If you’re lucky, you’ve built your search routine out of a few general functions. Maybe you’re really lucky, and your changes are limited to one function. Hopefully, you can make your changes without reworking the structure of your existing code. Now consider a more drastic upgrade. Maybe you need to add a logging feature that works whenever you access the database, or perhaps your organi- zation has expanded from Access to SQL Server and you now have to connect to an entirely new and unfamiliar type of database. Maybe you need to have your program provide different levels of access, to change the user interface radically, or to create a dozen different search variants that are largely similar but slightly different. As you start to add these enhancements, you’ll find yourself making changes that range over your entire program. If you’ve been extremely disciplined in the first place, the job will be easier. By the end of the day, however, you’ll probably end up with a collection of loosely related functions, blocks of code that are tightly linked to specific controls in specific windows, and pieces of database code scattered everywhere. In other words, the more changes you make in a traditionally structured program, the more it tends toward chaos. When bugs start to appear, you’ll probably have no idea which part of the code they live in. And guess what happens when another programmer starts work on a similar program for inventory management? Don’t even dream of trying to share your code. You both know that it will be more difficult to translate a routine into a usable form for another program than it will be to rewrite the code from scratch. In Chapter 6 you’ll see some examples that explain how object-oriented programming overcomes these disasters. But for now, it will help if you get a handle on how you can create an object in Visual Basic 2005. First There Were Structures . . . The precursor to classes was a programming time-saver called structures. A structure is a way of grouping data together, so that several variables become part of one conceptual whole. NOTE In earlier versions of Visual Basic, structures were called types. As you learned in Chapter 3, the word type has a completely different meaning in .NET—it encompasses all the different ingredients you’ll find in the class library. This is a potential point of confusion for classic VB developers migrating to .NET. For example, suppose you need to store several pieces of information about a person. You could create separate variables in your code to represent the person’s birth date, height, name, and taste in music. If you leave these variables separate, you’ve got a potential problem. Your code becomes more complicated, and it’s not obvious that these separate variables have anything to do with each other. And if you have to work with information for more than one person at a time, you have to create a frightening pile of variables bvb_02.book Page 138 Thursday, March 30, 2006 12:39 PM Object-Oriented Programming 139 to keep track of all the information. It’s likely that you’ll soon make the mis- take of changing the wrong person’s age, forgetting to give someone a birth date, or misplacing their favorite CD collection. Here’s where structures come into the picture. A Very Simple Person Structure To group this information together, you can create the following structure: Public Structure Person Dim FirstName As String Dim LastName As String Dim BirthDate As Date End Structure Where can you place this code? In VB 2005 you can put public structures anywhere at the file or module level. The only limitation is that they can’t be inside a function or a subroutine. If you define a private structure, you can put it inside the class or module where you want to use it. Now you can use this structure to create a Person object in some other place in your code, and you can set that Person’s information like so: Dim Lucy As Person Lucy.FirstName = "Lucy" Lucy.LastName = "Smith" Lucy.BirthDate = DateTime.Now In this case, we set the birthday to the current time to indicate that Lucy has just been brought to life. The preceding code is easy to read. When you change a variable, you know which person it relates to. If you want to create more than one Person object, it’s easy, and there will be a lot less code. Best of all, you can pass an entire Person through just one parameter to a function or subroutine that uses it, as follows: Public Sub GoShopping(ByVal Shopper As Person) ' Some code here to manage the mall process. End Sub NOTE The word object is often used in a fairly loose fashion to mean all sorts of things. But technically speaking, an object is a live instance of a structure or a class that’s floating around in memory. In other words, you use a structure to define a person at design time, and you use that structure to create as many Person objects as you need at runtime, each of which stores its own personal data. Structures are really “super variables.” You’re probably familiar with this concept if you’ve worked with databases, even if you’ve never actually created a structure or a class. In a database, each person is represented by a record (also known as a row), and each record has the same series of fields to describe it. bvb_02.book Page 139 Thursday, March 30, 2006 12:39 PM 140 Chapter 5 Basically, there is one important similarity between structures and classes: Both are defined only once, but can be created as many times as you want, just about anywhere in your code. This means you only need to define one Person structure, but you can build families, convention centers, and bowling clubs without introducing any new code. Making a Structure That Has Brains What about a structure with built-in intelligence? For example, what if we could make a Person structure that wouldn’t let you set a birth date that was earlier than 1800, could output a basic line of conversation, and would notify you when its birthday arrives? This is what you get with a class: a structure that can include data and code. (Actually, Visual Basic 2005 structures can contain code, though there are subtle differences between structures and classes, which we’ll explore a little later in this chapter. In practice, classes are usually the way to go because structures have subtle limitations. Most programmers see structures simply as examples of backward compatibility—like little pieces of living history accessible from the modern Visual Basic programming language.) Consider our Person as a full-fledged class: Public Class Person ' Data for the Person Public FirstName As String Public LastName As String Public BirthDate As Date ' Built-in feature to get the Person object to introduce itself. Public Function GetIntroduction() As String Dim Intro As String Intro = "My name is " & FirstName & " " & LastName & ". " Intro &= "I was born on " & BirthDate.ToString() Return Intro End Function End Class Notice that this Person class looks similar to the Person structure you saw earlier. It has the same three variables, except that now you must be careful to mark them with the Public keyword. (By default, variables inside a class are private, which means that only the code inside the class can see or change them. In this case, this behavior isn’t what you want, because it would prevent your code from changing or retrieving this information.) The Person class also adds a method (here, a function) called GetIntroduction(), which is placed right in the class. This means that every Person object is going to have a built- in feature for introducing itself. bvb_02.book Page 140 Thursday, March 30, 2006 12:39 PM Object-Oriented Programming 141 NOTE To create a file quickly for a new class in Visual Studio, load up a project and choose Project Add Class from the menu. Similarly, if you were to make a class modeling a microwave oven, you might have data such as the microwave’s manufacturer and the current power level, along with a CookFood() method. Now you can see how classes help organize code. Methods that are specific to a particular class are embedded right in the class. Instantiating an Object Returning to our Person class, you’ll find that it’s quite easy to use it to create a live object (a process called instantiation): Dim Lucy As New Person() Lucy.FirstName = "Lucy" Lucy.LastName = "Smith" Lucy.BirthDate = DateTime.Now MessageBox.Show(Lucy.GetIntroduction(), "Introduction") This code produces the output shown in Figure 5-1. Figure 5-1: An introductory class NOTE To see this code in action and create a Lucy object, you can use the ObjectTester project included with the samples for this chapter. Notice that to create an object based on a class, you use a Dim statement with the New keyword. The New keyword is required to actually create the object. Alternatively, you could use the following code: Dim Lucy As Person ' Define the Lucy object variable. Lucy = New Person() ' Create the Lucy object. This code is almost exactly the same. The only difference is that it gives you the ability to separate the two lines. This approach could be useful if you want to define the Lucy variable in one spot and then create the Lucy object in another spot, such as a separate method. Notice that there is no Set statement used. (The Set statement was a hallmark of objects in Visual Basic 6.) bvb_02.book Page 141 Thursday, March 30, 2006 12:39 PM 142 Chapter 5 TIP In classic Visual Basic, using the New keyword in a Dim statement could get you into trouble by defining a dynamically creatable object that could spring to life at any moment and just wouldn’t stay dead. Now the syntax Dim VarName As New ClassName defines a variable and instructs Visual Basic to instantiate the object immediately, just as you would expect. To release an object, set it equal to Nothing, as shown here: Lucy = Nothing This tells Visual Basic that the object is no longer needed. Strictly speaking, you won’t often need to use this statement, because the variable will be automatically cleared as soon as it goes out of scope. For example, if you define a variable in a subroutine, the variable will be set to nothing as soon as the subroutine ends. If you want to clear an object variable before this, use the Nothing keyword. Objects Behind the Scenes When you create an object based on a class, you’ll find that it behaves differently from other variables. This unusual behavior was introduced in connection with arrays in Chapter 3, although it is significant enough to examine in more detail here. The issue is that classes are reference types, which means that, behind the scenes, .NET tracks them using a reference that points to some location in memory. All reference types exhibit some quirky behavior when you copy or compare instances. Copying Objects Consider the following code: ' Create two people objects. Dim Lucy As New Person() Dim John As New Person() ' Enter information in the Lucy object. Lucy.FirstName = "Lucy" ' Copy the reference, not the value. The original John object is abandoned. John = Lucy The last line is the most significant. If you were expecting objects to behave like variables of the Integer or String data type, you might expect that this line copies Lucy’s information into John. Instead, the existing John object is abandoned, and the reference to it in the John variable is replaced by a reference to the Lucy object. At the end of the last line, there is really only one object ( Lucy) remaining, with two different variables that you can use to access it. bvb_02.book Page 142 Thursday, March 30, 2006 12:39 PM Object-Oriented Programming 143 Let’s continue with the following code: John.FirstName = "John" ' Now Lucy.FirstName is also John! This is an example of reference equality. In most cases it is more useful than value equality for working with objects. It’s definitely faster, because all .NET needs to do is copy a memory pointer from one variable to another (rather than copy the entire block of memory that represents the object, which could be quite large). NOTE This is the key difference between VB 2005 structures and classes: Structures are value types, while classes are reference types. As with all value types, assignment and compar- ison operations work on the contents of the object, not the memory reference. This can make large structures much slower and less efficient to work with than classes. Many classes support cloning, which allows you to copy the contents of an object when needed by calling a Clone() method. The familiar Array class is an example. To create an object that supports cloning, you need to go to a little extra work and implement a special interface. The next chapter explains inter- faces and demonstrates this technique. Comparing Objects Reference types also have their own rules for comparison. Notably, you can’t use the equal sign ( =). This is to eliminate confusion regarding the true mean- ing of an “equals” comparison. With two variables, a comparison determines whether the values of both variables are the same. With two objects, a compari- son doesn’t determine whether the contents are the same, but rather whether both object references are pointing to the same object. In other words, if objOne Is objTwo , there really is only one object, which you can access with two differ- ent variable names. If intOne = intTwo, however, it means that two separate variables are storing identical information. Here’s an example that demonstrates this oddity: If Lucy Is John Then ' Contrary to what you might expect, the Lucy and John ' variables are pointing to the same object. End If ' The following won't work, because you can't compare object contents directly. ' If Lucy = John Then ' This comparison can't be made automatically. ' Instead, the object would need to provide a method that ' compares every property (or just the important ' ones that are necessary to define equality). End If bvb_02.book Page 143 Thursday, March 30, 2006 12:39 PM 144 Chapter 5 The difference between reference equality and value equality takes a little getting used to. Sometimes it helps to understand why the creators of VB (and most other modern languages, such as Java and C#) choose to implement this sort of behavior. The reality is that objects are often large blobs of memory with plenty of information and functionality packed in. Although it’s possible for an environment like the Common Language Runtime to provide a standard way to compare two blobs of memory to see whether they contain the same data, it would be unacceptably slow. Simple value types tend to be much smaller scraps of information that are readily available and can be compared with lightning speed. There’s also the issue of identity, which reference types have and value types don’t. Essentially, if two value types have the same data, they are the same. However, if two reference types have the same data, they are equiva- lent but separate. In other words, it’s possible to have two identical but separate Person objects. (Maybe it’s just a freakish coincidence.) The Null Value Error The most common error you will receive while working with reference types is the common NullReferenceException, which warns you that “Value null was found where an instance of an object was required.” What this means is that you’ve tried to work with an object that you have defined but have not instanti- ated. Typically, this is caused when you forget to use the New keyword. Here’s the mistake in action: Dim Lucy As Person ' No New keyword is used; this is a definition only. Lucy.FirstName = "Lucy" ' Won't work because Lucy doesn't exist yet! It’s a small mistake that you will soon learn to avoid, but being able to recognize it ensures that it will never frustrate you for long. Classes in Pieces As you’ve already learned, Visual Basic 2005 is flexible enough to let you define as many classes as you want in the same file. This feature has been around since .NET 1.0 first hit the scene. However, VB 2005 adds a new wrinkle. Now, not only can you place multiple classes in one file; you can also split a single class across different files. (This might be worthwhile if you’re working with extremely large classes.) In order to pull off this trick, you need to add the Partial keyword to your class declaration. Otherwise, the VB compiler assumes you’ve made a mistake. For example, you could split the Person class into two pieces in sev- eral ways. First, put this part of the declaration in a file named Person1.vb: Partial Public Class Person Public FirstName As String Public LastName As String Public BirthDate As Date End Class bvb_02.book Page 144 Thursday, March 30, 2006 12:39 PM Object-Oriented Programming 145 Then put this part into a file named Person2.vb: Partial Public Class Person Public Function GetIntroduction() As String Dim Intro As String Intro = "My name is " & FirstName & " " & LastName & ". " Intro &= "I was born on " & BirthDate.ToString() Return Intro End Function End Class This doesn’t change how your program works one bit. When you compile your application, these two pieces are fused together into one class, exactly as though you had coded them in the same file. NOTE Technically, you only need to add the Partial keyword to one of the class declarations. In other words, if you split a class into ten pieces, you need to use Partial on at least one of those pieces. However, it’s good style to use it on every declaration, so you don’t forget that you only have a piece of the picture when you’re editing one of the files. You probably won’t use partial classes too often. Although they can help you break down large classes into more manageable bits, the presence of large classes in the first place probably indicates that you need a better design (one that splits your code into smaller classes). However, Visual Studio uses partial classes to hide details that you don’t need to see, like the automatically generated form code that you saw in Chapter 4. The idea is that the class is split into two pieces—the one you fill with your application code and the other that has the low-level plumbing you can safely ignore. Enhancing a Class with Properties A class provides another important ingredient, called properties. Right now, the Person class uses three variables, and all of these variables are exposed to the outside world. This exposure makes life convenient but dangerous. Suppose a microwave oven did not have a control panel; instead, the user was supposed to control it directly through the circuitry in the back. In such a situation, numerous problems could occur, ranging from unsatisfactory results (for example, burning dinner by forgetting to turn the power off at the right time) to safety hazards (for example, burning people by running the microwave with the door open). In order to make sure that a class does only the legitimate things it is intended to do, its developer has to make it a well-encapsulated black box, hiding as much of the internal details as possible and providing it with a con- trol panel. This means that every class should perform its own basic error checking. It also means that a class should use only private variables, which are hidden from the outside world. To let the calling code change a private variable in a class in a controlled manner, you use properties. bvb_02.book Page 145 Thursday, March 30, 2006 12:39 PM [...]... CloseFile ' Close the current file (indicated by FileName) End Sub End Class The more you understand about Visual Basic 2005, the more you’ll realize that the language is completely built around objects and the principles of object-oriented programming Some of the conventions of traditional Visual Basic remain, but really just as a thin veneer over the OO reality 168 C h ap te r 5 bvb_02 .book Page 169... class, the bottom portion display all the information about the properties, methods, events, and private variables contained in that class Together, these details make up the members of the class 170 C h ap te r 5 bvb_02 .book Page 171 Thursday, March 30, 2006 12:39 PM You can see a similar view of namespaces and the NET class library using the Object Browser To display the Object Browser, choose View Other... created as a form-level variable named CurrentPerson when the form is created This variable is declared WithEvents, which means that its events are automatically available 156 C h ap te r 5 bvb_02 .book Page 157 Thursday, March 30, 2006 12:39 PM An event handler for the form’s Load event calls the RefreshData() subroutine when the form is first loaded The RefreshData() subroutine updates the on-screen controls... Name Change, as shown in Figure 5-5 (This example is also included with the sample code for this chapter, in the EventTester project.) O bj ect -O r ien t ed Prog r am mi ng 155 bvb_02 .book Page 156 Thursday, March 30, 2006 12:39 PM Figure 5-5 : The event tester The form class looks like this: Public Class EventTester ' Create the Person as a form-level variable Private WithEvents CurrentPerson As New... characteristics of Visual Basic 6, this system had some problems For example, if two objects refer to each other, they could never be removed, even though they might be floating in memory, totally detached from the rest of your program This problem is called a circular reference Object Death in Visual Basic 2005 In NET, objects always remain in memory until the garbage collector finds them The garbage... notice that the parameter names in the previous example conflict with the property names of the class However, the parameter names have precedence, so the code will work the way it is written To refer directly to one of the properties with the same name in the New subroutine, you would need to use the Me keyword (as in Me.FirstName) The constructor in this example allows you to preload information into... that the PersonA object itself points to another object (PersonB), which points back to PersonA In Visual Basic 6, this circular reference would force the abandoned Person objects to remain floating in memory, because neither one has been fully released With VB 2005 garbage collection, the garbage collector will notice that these objects are cut off from the rest of your program, and it will free the. .. ng 149 bvb_02 .book Page 150 Thursday, March 30, 2006 12:39 PM Figure 5-2 : Testing the Person object Multiple Constructors Another exciting feature of VB 2005 is the ability to define multiple constructors for a class Once you’ve done this, then when you create an instance of that class, you can decide which constructor you want to use Each constructor must have its own distinct parameter list (In other... procedures, then constructors, and then other methods Visual Basic 2005 gives you as much freedom to arrange the internal details of a class as it gives you to arrange different classes and modules in a file To try out the Person class and see how a simple client interacts with it, you can use the ObjectTester project included with the sample code for this chapter (see Figure 5-2 ) O bj ect -O r ien t... event handler code in another Events with Different Signatures You can also create an event that supplies information through additional parameters Remember, the recommended format for a NET event is a parameter for the sender, combined with a parameter for the additional information The additional information is provided through a class that derives from System.EventArgs For example, our DataChanged . version of Visual Basic or another programming language. Even so, you’ll probably still want to read through the majority of this chapter and the next to explore the object-oriented features of VB. VB 2005 and to get the big picture of the world of classes, interfaces, and object relationships. New in .NET Visual Basic 2005 s enhanced OOP features first appeared in .NET 1.0, when they. variables bvb_02 .book Page 138 Thursday, March 30, 2006 12:39 PM Object-Oriented Programming 139 to keep track of all the information. It’s likely that you’ll soon make the mis- take of changing the