Professional VB 2005 - 2006 phần 3 potx

110 216 0
Professional VB 2005 - 2006 phần 3 potx

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

To include a method as part of your interface, you can simply declare a Public routine: Public Sub AMethod() End Sub Notice that there is no code in this routine. Any code would be implementation and is not part of the interface. Only the declaration of the method is important when discussing interfaces. This can seem confusing at first, but it is an important distinction, since the separation of the interface from its imple- mentation is at the very core of object-oriented programming and design. Since this method is declared as Public, it is available to any code outside the class, including other applications that may make use of the assembly. If the method has a property, you can declare it as part of the interface by using the Property keyword: Public Property AProperty() As String End Property You can also declare events as part of the interface by using the Event keyword: Public Event AnEvent() Finally, you can include actual variables, or attributes, as part of the interface: Public AnInteger As Integer This is strongly discouraged, because it directly exposes the internal variables for use by code outside the class. Since the variable is directly accessible from other code, you give up any and all control over the way the value may be changed or by which code may be accessed. Rather than making any variable Public, it is far preferable to make use of a Property method to expose the value. In that way you can implement code to ensure that your internal variable is only set to valid values and that only the appropriate code has access to the value based on your application’s logic. Using the Native Interface In the end, the native (or primary) interface for any class is defined by looking at all the methods, prop- erties, events, and variables that are declared as anything other than Private in scope. This includes any methods, properties, events, or variables that are inherited from a base class. You’re used to interacting with the default interface on most objects, so this should seem pretty straight- forward. Consider a simple class: Public Class TheClass Public Sub DoSomething() End Sub 188 Chapter 5 08_575368 ch05.qxd 10/7/05 10:47 PM Page 188 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Public Sub DoSomethingElse() End Sub End Class This defines a class and, by extension, also defines the native interface that is exposed by any objects you instantiate based on this class. The native interface defines two methods, DoSomething and DoSomethingElse. To make use of these methods, you simply call them: Dim myObject As New TheClass() myObject.DoSomething() myObject.DoSomethingElse() This is the same thing you’ve done in Chapter 4 and so far in this chapter. However, let’s take a look at creating and using secondary interfaces, because they are a bit different. Secondary Interfaces Sometimes, it can be helpful for an object to have more than one interface, thus allowing you to interact with the object in different ways. Inheritance allows you to create subclasses that are a specialized case of the base class. For example, your Employee is a Person. However, there are times when you have a group of objects that are not the same thing, but you want to be able to treat them as though they were the same. You want all these objects to act as the same thing, even though they are all different. For instance, you may have a series of different objects in an application, product, customer, invoice, and so forth. Each of these would have default interfaces appropriate to each individual object— and each of them is a different class — so there’s no natural inheritance relationship implied between these classes. At the same time, you may need to be able to generate a printed document for each type of object. So, you’d like to make them all act as a printable object. Chapter 7 discusses the is-a and act-as relationships in more detail. To accomplish this, you can define a generic interface that would enable generating such a printed docu- ment. You can call it IPrintableObject. By convention, this type of interface is typically prefixed with a capital I to indicate that it is a formal interface. Each of your application objects can choose to implement the IPrintableObject interface. Every object that implements this interface must provide code to provide actual implementation of the interface, which is unlike inheritance, where the code from a base class is automatically reused. 189 Inheritance and Interfaces 08_575368 ch05.qxd 10/7/05 10:47 PM Page 189 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com By implementing this common interface, however, you are able to write a routine that accepts any object that implements the IPrintableObject interface and print it —while remaining totally oblivious to the “real” datatype of the object or the methods its native interface might expose. Before you see how to use an interface in this manner, let’s walk through the process of actually defining an interface. Defining the Interface You define a formal interface using the Interface keyword. This can be done in any code module in your project, but a good place to put this type of definition is in a standard module. An interface defines a set of methods ( Sub, Function, or Property) and events that must be exposed by any class that chooses to implement the interface. Add a module to the project using Project ➪ Add Module and name it Interfaces.vb. Then, add the following code to the module, outside the Module code block itself: Public Interface IPrintableObject End Interface Module Interfaces End Module A code module can contain a number of interface definitions, and these definitions must exist outside any other code block. Thus, they don’t go within a Class or Module block; they are at a peer level to those constructs. Interfaces must be declared using either Public or Friend scope. Declaring a Private or Protected interface will result in a syntax error. Within the Interface block of code, you can define the methods, properties, and events that will make up your particular interface. Since the scope of the interface is defined by the Interface declaration itself, you can’t specify scopes for individual methods and events, they are all scoped the same as the interface itself. For instance, add the following code: Public Interface IPrintableObject Function Label(ByVal index As Integer) As String Function Value(ByVal index As Integer) As String ReadOnly Property Count() As Integer End Interface This defines a new datatype, somewhat like creating a class or structure, that you can use when declar- ing variables. For instance, you can now declare a variable of type IPrintableObject: Private printable As IPrintableObject 190 Chapter 5 08_575368 ch05.qxd 10/7/05 10:47 PM Page 190 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com You can also have your classes implement this interface, which will require each class to provide imple- mentation code for each of the three methods defined on the interface. Before you implement the interface in a class, let’s see how you can make use of the interface to write a generic routine that can print any object that does implement IPrintableObject. Using the Interface Interfaces define the methods and events (including parameters and datatypes) that an object is required to implement if they choose to support the interface. This means that, given just the interface definition, you can easily write code that can interact with any object that implements the interface, even though you don’t know what the native datatypes of those objects will be. To see how you can write such code, let’s create a simple routine in your form that can display data to the Output window in the IDE from any object that implements IPrintableObject. Bring up the code window for your form and add the following routine: Public Sub PrintObject(obj As IPrintableObject) Dim index As Integer For index = 0 To obj.Count Debug.Write(obj.Label(index) & “: “) Debug.WriteLine(obj.Value(index)) Next End Sub Notice that you’re accepting a parameter of type IPrintableObject. This is how secondary interfaces are used, by treating an object of one type as though it was actually of the interface type. As long as the object passed to this routine implements the IPrintableObject interface, your code will work fine. Within the PrintObject routine, you’re assuming that the object will implement three elements — Count, Label, and Value — as part of the IPrintableObject interface. Secondary interfaces can include methods, properties, and events, much like a default interface, but the interface itself is defined and implemented using some special syntax. Now that you have a generic printing routine, you need a way to call it. Bring up the designer for Form1, add a button, and name it btnPrint. Double-click the button and put this code behind it: Private Sub btnPrint_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnPrint.Click Dim obj As New Employee(“Andy”) obj.EmployeeNumber = 123 obj.BirthDate = #1/1/1980# obj.HireDate = #1/1/1996# PrintObject(obj) End Sub This code simply initializes an Employee object and calls the PrintObject routine. 191 Inheritance and Interfaces 08_575368 ch05.qxd 10/7/05 10:47 PM Page 191 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Of course, this code produces compiler errors, because PrintObject is expecting a parameter that implements IPrintableObject and Employee implements no such interface. Let’s move on and implement that interface in Employee so that you can see how it works. Implementing the Interface Any class (other than an abstract base class) can implement an interface by using the Implements key- word. For instance, you can implement the IPrintableObject interface in Employee by adding the following line: Public Class Employee Inherits Person Implements IPrintableObject This will cause the interface to be exposed by any object created as an instance of Employee. Adding this line of code triggers the IDE to add skeleton methods for the interface to your class. All you need to do is provide implementations for the methods. To implement an interface, you must implement all the methods and properties defined by that interface. Before actually implementing the interface, however, let’s create an array to contain the labels for the data fields so that you can return them via the IPrintableObject interface. Add the following code to the Employee class: Public Class Employee Inherits Person Implements IPrintableObject Private mLabels() As String = {“ID”, “Age”, “HireDate”} Private mHireDate As Date Private mSalary As Double To implement the interface, you need to create methods and properties with the same parameter and return datatypes as those defined in the interface. The actual name of each method or property doesn’t matter because you’ll be using the Implements keyword to link your internal method names to the external method names defined by the interface. As long as the method signatures match, you are all set. This applies to scope as well. Although the interface and its methods and properties are publicly avail- able, you don’t have to declare your actual methods and properties as Public. In many cases, you can implement them as Private, so they don’t become part of the native interface and are only exposed via the secondary interface. However, if you do have a Public method with a method signature, you can use it to implement a method from the interface. This has the interesting side effect that this method provides implementation for both a method on the object’s native interface and one on the secondary interface. In this case, you’ll use a Private method, so it is only providing implementation for the IPrintableObject interface. You can implement the Label method by adding the following code to Employee: 192 Chapter 5 08_575368 ch05.qxd 10/7/05 10:47 PM Page 192 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Private Function Label(ByVal index As Integer) As String _ Implements IPrintableObject.Label Return mLabels(index) End Function This is just a regular Private method that returns a String value from the preinitialized array. The interesting thing is the Implements clause on the method declaration. Private Function Label(ByVal index As Integer) As String _ Implements IPrintableObject.Label By using the Implements keyword in this fashion, you’re indicating that this particular method is the implementation for the Label method on the IPrintableObject interface. The actual name of the pri- vate method could be anything. It is the use of the Implements clause that makes this work. The only requirement is that the parameter datatypes and the return value datatype must match those defined by the IPrintableObject interface. This is very similar to using the Handles clause to indicate which method should handle an event. In fact, like the Handles clause, the Implements clause allows you to have a comma-separated list of inter- face methods that should be implemented by this one function. You can then move on to implement the other two elements defined by the IPrintableObject inter- face by adding this code to Employee: Private Function Value(ByVal index As Integer) As String _ Implements IPrintableObject.Value Select Case index Case 0 Return CStr(EmployeeNumber) Case 1 Return CStr(Age) Case Else Return Format(HireDate, “Short date”) End Select End Function Private ReadOnly Property Count() As Integer _ Implements IPrintableObject.Count Get Return UBound(mLabels) End Get End Property You can now run this application and click the button. The Output window in the IDE will display your results, showing the ID, age, and hire date values as appropriate. Any object could create a similar implementation behind the IPrintableObject interface, and the PrintObject routine in your form would continue to work regardless of the native datatype of the object itself. 193 Inheritance and Interfaces 08_575368 ch05.qxd 10/7/05 10:47 PM Page 193 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Reusing Common Implementation Secondary interfaces provide a guarantee that all objects implementing a given interface will have exactly the same methods and events, including the same parameters. The Implements clause links your actual implementation to a specific method on an interface. For instance, your Value method is linked to IPrintableObject.Value using the following clause: Private Function Value(ByVal index As Integer) As String _ Implements IPrintableObject.Value Sometimes, your method might be able to serve as the implementation for more than one method, either on the same interface or on different interfaces. Add the following interface definition to Interfaces.vb: Public Interface IValues Function GetValue(ByVal index As Integer) As String End Interface This interface defines just one method, GetValue. Notice that it defines a single Integer parameter and a return type of String, the same as the Value method from IPrintableObject. Even though the method name and parameter variable name don’t match, what counts here is that the parameter and return value datatypes do match. Now bring up the code window for Employee. You’ll have it implement this new interface in addition to the IPrintableObject interface: Public Class Employee Inherits Person Implements IPrintableObject Implements IValues You already have a method that returns values. Rather than reimplementing that method, it would be nice to just link this new GetValues method to your existing method. You can easily do this because the Implements clause allows you to provide a comma-separated list of method names: Private Function Value(ByVal index As Integer) As String _ Implements IPrintableObject.Value, IValues.GetValue Select Case Index Case 0 Return CStr(EmployeeNumber) Case 1 Return CStr(Age) Case Else Return Format(HireDate, “Short date”) End Select End Function This is very similar to the use of the Handles keyword as discussed in Chapter 4. A single method within the class, regardless of scope or name, can be used to implement any number of methods as defined by other interfaces as long as the datatypes of the parameters and return values all match. 194 Chapter 5 08_575368 ch05.qxd 10/7/05 10:47 PM Page 194 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Combining Interfaces and Inheritance You can combine implementation of secondary interfaces and inheritance at the same time. When you inherit from a class that implements an interface, your new subclass automatically gains the interface and the implementation from the base class. If you specify that your base class methods are overridable, then the subclass can override those methods. This will not only override the base class implementation for your native interface, but will also override the implementation for the interface. For instance, you could declare the Value method as follows: Public Overridable Function Value(ByVal index As Integer) As String _ Implements IPrintableObject.Value, IValues.GetValue Now it is Public, so it is available on your native interface, and it is part of both the IPrintableObject and IValues interfaces. This means that you can access the property three ways in client code: Dim emp As New Employee() Dim printable As IPrintableObject = emp Dim values As IValues = emp Debug.WriteLine(emp.Value(0)) Debug.WriteLine(printable.Value(0)) Debug.WriteLine(values.GetValue(0)) Note that you’re also now using the Overrides keyword in the declaration. This means that a subclass of Employee, such as OfficeEmployee, can override the Value method. The overridden method will be the one invoked, regardless of whether you call the object directly or via an interface. Combining the implementation of an interface in a base class along with overridable methods can pro- vide a very flexible object design. Summary In this chapter and in Chapter 4, you’ve seen how Visual Basic allows you to create and work with classes and objects. Visual Basic provides the building blocks for abstraction, encapsulation, polymor- phism, and inheritance. In this chapter, you’ve seen how to create both simple base classes as well as abstract base classes. You’ve also explored how you can define formal interfaces, a concept quite similar to an abstract base class in many ways. You’ve also walked through the process of subclassing, creating a new class that derives both interface and implementation from a base class. The subclass can be extended by adding new methods or altering the behavior of existing methods on the base class. Visual Basic provides you with all the capabilities you need to build robust and sophisticated object- oriented applications. In the next chapter, we’ll pull this all together by discussing abstraction, encapsu- lation, polymorphism, and inheritance as they pertain to building practical software. 195 Inheritance and Interfaces 08_575368 ch05.qxd 10/7/05 10:48 PM Page 195 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 08_575368 ch05.qxd 10/7/05 10:48 PM Page 196 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com The Common Language Runtime You’ve seen how to create simple applications and looked at how to create classes. Now it’s time not only to start tying these elements together but also to start looking at how to dispose of some of the classes that you have created. The architects of .NET realized that all procedural languages require certain base functionality. For example, many languages ship with their own runtime that provides features such as memory management. But what if instead of each language shipping with its own runtime implementation, all languages used a common runtime? This would provide languages with a standard environment and access to all of the same features. This is exactly what the common language runtime (CLR) provides. The CLR manages the execution of code on the .NET platform. Visual Basic developers can view the CLR as a better Visual Basic runtime. However, this runtime, unlike the old stand-alone Visual Basic runtime, is common across all of .NET. The functionality exposed by the CLR is available to all .NET languages; more importantly, all of the features available to other .NET languages via the CLR are available to Visual Basic developers. Visual Basic developers have been asking for better support for many advanced features, includ- ing operator overloading, implementation inheritance, threading, and the ability to marshal objects. Building such features into a language is not trivial. What the CLR did was allow Microsoft to con- centrate on building this plumbing one time and then reuse it across multiple different program- ming languages. Since the CLR supports these features and because Visual Basic .NET is built on top of the CLR, Visual Basic can use these features. The result is that going forward, Visual Basic is the equal of every other .NET language, with the CLR eliminating many of the shortcomings of the previous versions of Visual Basic. This chapter gets down into the weeds of the application runtime environment to look at: 09_575368 ch06.qxd 10/7/05 10:49 PM Page 197 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com [...]... finally double-click the Equals method A window similar to the one shown in Figure 6 -3 will be displayed Figure 6 -3 209 Chapter 6 Figure 6 -3 shows the IL for the Equals method Notice how the Reflection API is used to navigate through the instance of the value type’s fields in order to determine if the values of the two objects being compared are equal Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com... of a single module having both the assembly code and manifest IL is a platform-independent way of representing managed code within a module Before IL can be executed, the CLR must compile it into the native machine code The default method is for the CLR to use the JIT (Just-in-Time) compiler to compile the IL on a method-by-method basis At runtime, as each method is called by an application for the... not enough to be successful Successfully applying the object-oriented capabilities of Visual Basic to create applications requires an understanding of object-oriented programming This chapter applies Visual Basic’s object-oriented syntax and shows how it allows you to build object-oriented applications It further discusses the four major object-oriented concepts — abstraction, encapsulation, polymorphism,... applications, Visual Studio provides a built-in tool for constructing simple msi installations New with Visual Studio 2005 is the idea of a Click-Once deployment project These deployment settings can be customized for your project solution, allowing you to integrate the deployment project with your application output 202 Simpo PDF The Common Language Runtime Click-Once deployment provides an entirely new... your code The answer is that Visual Studio 2005, like Visual Studio 20 03, ships with a third-party tool called an obfuscator The role of the obfuscator is to make it so that the IL Disassembler cannot build a meaningful representation of your application logic It is beyond the scope of this chapter to completely cover the obfuscator that ships with Visual Studio 2005 However, to access this tool, you go... in Figure 6-1 Not only does the line with Method1 have a visual hint of the issue, but a task has also been automatically added to the Task window 206 The Common Language Runtime Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Figure 6-1 If the developer leaves this code unchanged and then compiles it, the application will compile correctly As you see in Figure 6-2 , the compilation... request is essentially lost This means that compilation to native code is more valuable to client-side applications Unfortunately, using Ngen.exe requires running it on each client machine, which can become cost-prohibitive in certain installation scenarios and in particular if you use any form of self-updating application logic Another issue relates to using reflection, which allows you to reference... about which you are learning It Version - http://www.simpopdf.com Merge and Split Unregisteredhas the advantages of central application maintenance combined with a richer client interface and fewer server communication requirements that you have become familiar with in Windows Forms applications Click-Once deployment is discussed in greater detail in Chapter 19 Cross-Language Integration Prior to NET,... Visual Basic represent strings using the BSTR structure, C++ offers char and wchar datatypes, and MFC offers the CString class And the fact that the C++ int datatype is a 32 -bit value, whereas the Visual Basic 6 Integer datatype is a 16-bit value, makes it difficult to pass parameters between applications written using different languages To help resolve this problem, C has become the lowest common denominator... 3- 1 is a simplification of what takes place in the managed heap for NET ❑ ❑ 218 State 1 — Shows a compressed memory heap with a reference to the end point on the heap State 2 — Object B, although no longer referenced, remains in its current memory location The memory has not been freed and does not alter the allocation of memory or of other objects on the heap The Common Language Runtime ❑ State 3 . native datatype of the object itself. 1 93 Inheritance and Interfaces 08_57 536 8 ch05.qxd 10/7/05 10:47 PM Page 1 93 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Reusing Common. native machine code. The default method is for the CLR to use the JIT (Just-in-Time) compiler to compile the IL on a method-by-method basis. At runtime, as each method is called by an application. deploy- ment project with your application output. 202 Chapter 6 09_57 536 8 ch06.qxd 10/7/05 10:49 PM Page 202 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Click-Once

Ngày đăng: 12/08/2014, 23:23

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan