Você está na página 1de 12

IUnknown

This interface enables clients to get pointers to other interfaces on a specified object through the IUnknown::QueryInterface method, and manage the existence of the object through the IUnknown::AddRef and IUnknown::Release methods. All other COM interfaces are inherited, directly or indirectly, fromIUnknown. Therefore, the three methods in IUnknown are the first entries in the vtable for every interface. Methods The following table shows the methods for this interface in alphabetical order. Method IUnknown::AddRef Description Increments the reference count for an interface on an object. It should be called for every new copy of a pointer to an interface on a specified object. Returns a pointer to a specified interface on an object to which a client currently holds an interface pointer. This method must call IUnknown::AddRef on the pointer it returns. Decrements the reference count for the calling interface on a object. If the reference count on the object falls to zero, the object is freed from memory.

IUnknown::QueryInterface

IUnknown::Release

IUnknown::AddRef This method increments the reference count for an interface on an object. It should be called for every new copy of a pointer to an interface on a specified object. ULONG AddRef(void); Parameters None. Return Values Returns an integer from 1 to n, the value of the new reference count. This information is meant to be used for diagnostic/testing purposes only, because, in certain situations, the value may be unstable. Remarks Objects use a reference counting mechanism to ensure that the lifetime of the object includes the lifetime of references to it. You use IUnknown::AddRef to stabilize a copy of an interface pointer. It can also be called when the life of a cloned pointer must extend beyond the lifetime of the original pointer. The cloned pointer must be released by calling the IUnknown::Release method. Objects must be able to maintain (231) 1 outstanding pointer references. Therefore, the internal reference counter that IUnknown::AddRef maintains must be a 32-bit unsigned integer.

Copyright - IT Engg Portal www.itportal.in

IUnknown::QueryInterface This method returns a pointer to a specified interface on an object to which a client currently holds an interface pointer. This method must call theIUnknown::AddRef method on the pointer it returns. HRESULT QueryInterface( REFIID iid, void** ppvObject ); Parameters iid [in] Identifier of the interface being requested. ppvObject [out] Address of the pointer variable that receives the interface pointer requested in riid. Upon successful return, *ppvObject contains the requested interface pointer to the object. If the object does not support the interface specified in iid, *ppvObject is set to NULL. Return Values S_OK indicates that the interface is supported. E_NOINTERFACE indicates that the interface is not supported. Remarks The QueryInterface method gives a client access to other interfaces on an object. For any one object, a specific query for the IUnknown interface on any of the object's interfaces must always return the same pointer value. This allows a client to determine whether two pointers point to the same component by calling QueryInterface on both and comparing the results. It is specifically not the case that queries for interfaces (even the same interface through the same pointer) must return the same pointer value. There are four Requirements for implementations of QueryInterface (In these cases, "must succeed" means "must succeed barring catastrophic failure."):

The set of interfaces accessible on an object through IUnknown::QueryInterface must be static, not dynamic. This means that if a call to QueryInterfacefor a pointer to a specified interface succeeds the first time, it must succeed again, and if it fails the first time, it must fail on all subsequent queries. It must be symmetric if a client holds a pointer to an interface on an object, and queries for that interface, the call must succeed. It must be reflexive if a client holding a pointer to one interface queries successfully for another, a query through the obtained pointer for the first interface must succeed. It must be transitive if a client holding a pointer to one interface queries successfully for a second, and through that pointer queries successfully for a third interface, a query for the first interface through the pointer for the third interface must succeed. IUnknown::Release This method decrements the reference count for the calling interface on a object. If the reference count on the object falls to zero, the object is freed from memory.
2

Copyright - IT Engg Portal www.itportal.in

ULONG Release(void); Parameters None. Return Values Returns the resulting value of the reference count, which is used for diagnostic/testing purposes only. If you need to know that resources have been freed, use an interface with higher-level semantics. Remarks If the IUnknown::AddRef method has been called on this object's interface n times and this is the n+1 call to IUnknown::Release, the implementation ofIUnknown::AddRef must cause the interface pointer to free itself. When the released pointer is the only existing reference to an object (whether the object supports single or multiple interfaces), the implementation must free the object. Aggregation of objects restricts the ability to recover interface pointers.

Inheritance and Interfaces


In addition to making complex systems easier to create and modify by encapsulating functionality within the methods and properties of objects, OOP supports class inheritance and the implementation of interfaces as ways of allowing new classes to be safely added to existing systems without requiring changes to existing code. We'll compare these two approaches to preparing for change, look at when each one is appropriate, and discuss a third approach, object composition, which is often the best choice of all. Inheritance Hierarchies Of all the OOP techniques available in Visual Basic .NET, inheritance is the least familiar to programmers coming from Visual Basic 6.0, where inheritance wasn't available. Even the non-Visual Basic object models that Visual Basic 6.0 programmers were likely to use, such as ADO or the Office libraries, rarely required an understanding of inheritance. Inheritance allows you to create a new class that is a variation on an existing (base) class, and to substitute the new derived class in any situation that originally called for the old base class. For example, if you have a class called SalesOrder, you can create a new derived class called WebSalesOrder: Public Class WebSalesOrder Inherits SalesOrder Any existing methods that take an object of type SalesOrder can remain unchanged and will now be able to handle WebSalesOrder objects as well. If SalesOrder has a Confirm method, you are assured that WebSalesOrder will also have a Confirm method. But if Confirm is marked as Overridable in the SalesOrder class, you can create a new Confirm method in the WebSalesOrder class that overrides the original method: Public Overrides Sub Confirm

Copyright - IT Engg Portal www.itportal.in

Perhaps the original Confirm method generated a fax to the customer, and the one in WebSalesOrder uses e-mail instead. The important part is that a method originally set up to accept objects of type SalesOrder will continue to work if you pass it a WebSalesOrder. And if that method calls the Confirm method of the object, the customer will get an email rather than a fax. Old code calls new code without making any changes to the old code. On the other hand, suppose there is a Total method that can work exactly the same for both classes. The derived WebSalesOrder class doesn't need to include any mention of that methodits implementation will automatically be inherited from the base class, and you'll be able to call the Total method for any WebSalesOrder object and have it act just like a SalesOrder object. Polymorphism Polymorphism, or substitutability, is one clear benefit of inheritance: any time you create an object from a derived class, you can use that object anywhere you can use an object from the base class. A WebSalesOrder "is a" SalesOrder, and it must be able to do everything a SalesOrder does, even if it does it in its own distinctive way. Polymorphism is the key to many of the advantages to OOP, and, as you'll see later in this document, it is not only available when you use inheritance, but also when you use interfaces. Polymorphism allows different kinds of objects that are all able to process a common set of messages to be used interchangeably, and to process those messages in their own ways. Your code to confirm orders doesn't have to know how to perform the confirmation, and it doesn't even have to know what kind of order is being confirmed. It only cares that it can successfully call the Confirm method of the order object it is working with, and it can rely on the object to handle the confirmation details: Public Sub ProcessOrder(order As SalesOrder) order.Confirm When you call the ProcessOrder procedure, you may pass it either a SalesOrder object or a WebSalesOrder object, and they will both work. Virtual Methods and Properties Virtuality only comes into play when you override base class methods in derived classes, and it is perhaps the most magical part of inheritance. The magic is that the Microsoft .NET runtime automatically finds and runs the most specialized implementation of any method or property that is called. For example, calling order.Confirm in the example above reaches down to the Confirm method of WebSalesOrder, where the base SalesOrder.Confirm method was overridden. However, order.Total calls the Total method of SalesOrder, because no specialized Total method was created in WebSalesOrder.

Copyright - IT Engg Portal www.itportal.in

Abstract Classes and Methods An abstract class is one that includes at least one method or property that must be overridden. For example, you could have created a SalesOrder class that didn't implement any way of confirming an order. Knowing that different kinds of orders must be confirmed in different ways, you can specify that a class derived from SalesOrder must override the Confirm method and provide its own implementation. This means that you couldn't ever create SalesOrder objects. Instead, you would only be able to create objects using derived classes that filled in the necessary details of how to perform an order confirmation. For that reason, the SalesOrder class would be marked MustInherit: Public MustInherit Class SalesOrder Public MustOverride Sub Confirm() Public Sub Total() 'Code to calculate a total End Sub If all the members of a class must be overridden, the class is called a pure abstract class. For example, your SalesOrder class could be just a list of all the methods and properties that need to be overridden by any derived class. But even if only one member must be overridden, the class will be identified as abstract using the MustInherit attribute. Type-Checking and Downcasting Now, what if some kinds of orders need confirmation and some don't? You could use a base SalesOrder class that doesn't include a Confirm method and only add Confirm to those derived classes that need it. But this will create a problem: You may want to create a procedure to handle all kinds of orders and confirm those that need confirmation. How would you know which ones to confirm? You could give the procedure a parameter of type SalesOrder, allowing all types derived from SalesOrder to be passed in. But then you would need to test for all the different confirmable types before calling the Confirm method. Furthermore, once you found an order type that was confirmable, you would need to downcast from the SalesOrder type, which does not have a Confirm method, to the derived type that does: Public Sub ProcessOrder(order As SalesOrder) If TypeOf(order) Is WebSalesOrder Then CType(order, WebSalesOrder).Confirm ElseIf TypeOf(order) Is EmailSalesOrder Then CType(order, EmailSalesOrder).Confirm ' and so on This kind of code is very hard to maintain. It forces you to modify the method any time a new type derived from SalesOrder is added to the system. That kind of coupling between old code and new code is exactly what you want to avoid. This would be almost as bad as implementing the confirmation code in this procedure for each different kind of sales order:
Copyright - IT Engg Portal www.itportal.in

If TypeOf(order) Is WebSalesOrder Then ' Put code here to confirm a WebSalesOrder ElseIf TypeOf(order) Is EmailSalesOrder Then ' Put code here to confirm an EmailSalesOrder ' and so on That pattern is even worse; not only must you change the procedure for every new type you create, you also no longer have each sales object handling its own confirmation, making it much harder for a programmer who needs to add a new type of sales order. How would that programmer know all the places where new code is needed to handle the new type? Another approach would be to create an intermediate abstract type called ConfirmableSalesOrder, derived from SalesOrder, with a MustOverride method, Confirm. You derive any types that need to handle confirmation from ConfirmableSalesOrder, and derive any other types directly from SalesOrder. The procedure now only has to check whether SalesOrder objects passed in were of type ConfirmableSalesOrder, and if so, it could use that type to call the Confirm method: If TypeOf(order) Is ConfirmableSalesOrder Then CType(order, ConfirmableSalesOrder).Confirm The CType downcasting conversion is still required to get to the Confirm method. But then, through the magic of virtuality, the call automatically passes down to whichever derived class the order was created with and runs the Confirm code defined there. So, the problem seems to be solved, but this is only a temporary solution. Have you guessed why? Suppose you next need to deal with the fact that some types of orders need a credit check. Some of the orders needing credit checks are also ones that get confirmed, but some aren't. Now you're in trouble. No Multiple-Inheritance in .NET You could try creating a CreditCheckableSalesOrder type that derives from SalesOrder. Some order types would derive from ConfirmableSalesOrder, and some from CreditCheckableSalesOrder, but what about those that need both confirmation and credit checks? One of the limitations on inheritance in the .NET Framework is that a type can only be derived from one base type. You can't have order types that derive from both ConfirmableOrder and CreditCheckableOrder. This may seem like an arbitrary or misguided limitation, but there are good reasons for it. Multipleinheritance is supported in C++. However, just about all the other modern object-oriented languages, including Java, have chosen not to allow multiple-inheritance. (Some advanced languages, such as Eiffel, have attempted to work out the kinks of multiple inheritance, and Eiffel for Microsoft .NET even provides the appearance of multiple inheritance within Microsoft .NET.) The biggest problem with multiple-inheritance is that it allows for ambiguity when the compiler needs to find the correct implementation of a virtual method. For example, suppose that Hound and Puppy are both derived from Dog, and then BabyBasset is derived from both Hound and Puppy:

Copyright - IT Engg Portal www.itportal.in

Figure 1. The problem with multiple-inheritance Now suppose that Dog has an overridable Bark method. Hound overrides it to sound like a howl, Puppy overrides it to sound like a yelp, and BabyBasset doesn't override Bark. If you create a BabyBasset object and call its Bark method, what will you get, a howl or a yelp? The .NET Framework prevents these kinds of problems by mandating that a derived class can only have a single base class. This limitation also means that every class is ultimately derived from a single great-grand-daddy class, System.Object. A singly rooted class hierarchy means that any Microsoft .NET object can be handled by a method that takes a parameter of type System.Object. One area where this is crucial is garbage collection, because the garbage collector that releases memory consumed by inaccessible objects must be able to handle all kinds of objects. A more familiar example of the benefits of allowing all objects to be upcast to a common type is event handlers: Public Sub MyEventHandler(By Val sender As _ System.Object, By Val e As System.EventArgs) This handler can be hooked up to events from any object or any combination of objects, because the sender parameter is typed as System.Object, and any Microsoft .NET object can be substituted for that. If necessary, you can use System.Reflection.GetType() to discover what type of object the sender is. Creating and Implementing Interfaces The subtleties concerning inheritance are very interesting, but what are we going to do about our sales orders that need confirmation and/or a credit-check? The answer is to use interfaces. The problems caused by multiple inheritance of classes result from potential conflicts among the various implementations of common methods in the inheritance chain. But suppose you knew that the classes you were inheriting from were pure abstract classes with no implementation? In that case, multiple-inheritance wouldn't cause any problems because there would be no implementations to
Copyright - IT Engg Portal www.itportal.in 7

cause conflicts. This is what interfaces provide: a way to inherit just a set of method and property specifications with no implementation to worry about and no problem inheriting from as many interfaces as you need. Although the phrase "interface inheritance" is often used, the correct term is interface implementation. It is possible for one interface to inherit from another, thereby extending its mandated set of methods to include those of the interface from which it inherits. However, to use interfaces in a Visual Basic .NET class, you implement them rather than inherit them: Public Interface IConfirmable Sub Confirm() End Interface Public Class WebSalesOrder() Inherits SalesOrder Implements IConfirmable Public Sub Confirm() Implements IConfirmable.Confirm ' Code to confirm a web order End Sub ' Other WebSalesOrder code End Class (In C#, a colon is used to express both class inheritance and interface implementation. This is probably why it is conventional to prefix all interface names with an "I". This allows C# programmers to easily distinguish base classes from interfaces.) You can create some types of sales orders that implement IConfirmable, some that implement ICreditCheckable, and some that do both. To check whether an order is confirmable, you use the same kind of code you would use to check whether or not it was derived from a particular base type and to downcast it to that type: Public Sub ProcessOrder(order As SalesOrder) If TypeOf(order) Is IConfirmable Then CType(order, IConfirmable).Confirm Interface Polymorphism You can use interfaces to provide the same benefits of polymorphism that are available when using derived classes. For example, you can pass any object made from a class that implements IConfirmable to a method that takes a parameter of type IConfirmable: Public Sub ConfirmOrder(order As IConfirmable) order.Confirm End Sub If WebSalesOrder and EmailSalesOrder both implement IConfirmable, you're able to pass either kind of object to the ConfirmOrder method. When it calls order.Confirm, the confirmation code that was implemented in the appropriate class will run. This works even if you don't name the class method Confirm, as long as you mark it as implementing the Confirm method of the IConfirmable interface:
8

Copyright - IT Engg Portal www.itportal.in

Public Class WebSalesOrder() Inherits SalesOrder Implements IConfirmable Public Sub ConfirmWebOrder() _ Implements IConfirmable.Confirm ' Code to confirm a web order End Sub This naming freedom is a useful feature. It comes in handy if your class implements two different interfaces that happen to have methods with the same name. Comparing Class Inheritance and Interface Implementation The most important technical distinction between creating a derived class and implementing an interface is that a derived class can only inherit from one base class, but a class can implement any number of interfaces. From a design standpoint, think of inheritance as expressing a specialization hierarchy. If WebSalesOrder "is a" special kind of SalesOrder, you might consider making it a derived class. However, you need to be very careful that you don't use inheritance when the specialization that distinguishes a derived class from a base class is a feature that other classes will also need to support. For adding those kinds of features or capabilities to a class, implementing interfaces will give you much greater flexibility. Inheritance is for Building Frameworks Designing useful inheritance hierarchies takes careful planning and a clear vision of how the hierarchy will be used. Think of it as a task to be performed by an accomplished software architect who is creating a framework that will be used by programmers building a variety of applications, not as a strategy to use when you are simply building a particular application. The .NET Framework itself includes many examples of inheritance at work, and you will need to create derived classes to perform many common programming activities. For example, you can create your own specialized exception classes derived from ApplicationException to carry customized error information. When you raise custom events, you send information to event handlers by creating a custom class derived from EventArgs. To create a type-specific collection, you'll derive from CollectionBase. And every time you create a Windows form in Visual Studio .NET, you are deriving from the Windows.Forms.Form base class. You need to be comfortable creating derived classes from base classes provided for you by framework architects, but be very cautious about creating your own base classes. Be sure that you are expressing a clear specialization hierarchy, and that you have clearly factored out the behaviors that you expect client programmers to override. The same caution applies to creating your own interfaces, but you are much less likely to paint yourself into a corner with interfaces than with inheritance, so give them preference if you feel you have a choice.
9

Copyright - IT Engg Portal www.itportal.in

Object Composition When considering the creation of your own inheritance hierarchies, don't be overly influenced by the appeal of code reuse. That alone is not a good reason to create a derived class. Instead of using inheritance to allow a new object to make use of code from an existing object, you can instead use a technique that goes by several different names: composition, containment, aggregation, or wrapping. This is a technique that you are likely to have used in Visual Basic 6.0, where inheritance wasn't an option. For example, to create a WebSalesOrder class that reuses all the code in the SalesOrder class and that also adds some new twists, you declare and create an instance of a SalesOrder object in your WebSalesOrder class. You can publicly expose the internal SalesOrder, or you can keep it private. Delegation If SalesOrder has a Total method, your WebSalesOrder can have a Total method that simply calls into the Total method of the private SalesOrder instance. This technique of passing along method calls (or property calls) to an internal object is often called delegation, but don't confuse it with the unrelated use of delegate objects to create callback functions and event handlers in Microsoft .NET. The events of your contained objects can be exposed in the wrapper class by declaring the contained object using the WithEvents keyword, just as in Visual Basic 6.0. Combining Composition with Interface Implementation The primary disadvantage of using object composition and delegation is that you don't automatically get polymorphism the way you do with derived classes. If your WebSalesOrder object simply contains a SalesOrder object, rather than being derived from one, then you can't pass a WebSalesOrder object to a method that has a parameter of type SaleOrder. You can easily work around this disadvantage by creating an ISalesOrder interface that your WebSalesOrder implements. You have the option of delegating to the methods and properties of the contained SalesOrder object. Or, as needed, WebSalesOrder can independently implement some of the methods and properties in the interface instead of delegating to the SalesOrder object. This is similar to overriding in derived classes. By combining object composition and delegation with interface implementation, you get code reuse and polymorphism without the design headaches of inheritance. For this reason, consider this as your first choice when you need to extend or specialize the functionality of classes. What's Different From Visual Basic 6.0? In Visual Basic 6.0, every time you create a class module, a hidden interface of the same name is automatically created for you. Consider the following Visual Basic 6.0 code: ' Visual Basic 6.0 code Dim myObject As MyClass Set myObject = New MyClass
Copyright - IT Engg Portal www.itportal.in 1 0

In this code, the first use of MyClass refers to the hidden interface containing empty methods and properties, and the second MyClass is the concrete class you wrote that implements those methods and properties. Visual Basic 6.0 shelters you from having to think about this use of interfaces, which is essential to the underlying COM plumbing. The Implements keyword in Visual Basic 6.0 allows you to make explicit use of interfaces and to take advantage of the same interface-based polymorphism that is available in Visual Basic .NET. The implementing class, however, must use a naming convention that incorporates the name of the interface: ' Visual Basic 6.0 IConfirmable class module Public Sub Confirm() End Sub ' VB6 WebSalesOrder class module Implements IConfirmable Private Function IConfirmable _Confirm() ' Implementation code here ' to confirm the order End Function Any Visual Basic 6.0 object implementing IConfirmable in this way can be passed to a procedure that takes a parameter of type IConfirmable, supporting the same type of polymorphism that interfaces provide in Visual Basic .NET: ' Visual Basic 6.0 or Visual Basic .NET Public Sub ConfirmOrder(order As IConfirmable) order.Confirm End Sub Although the syntax for working with interfaces is more flexible and less confusing in Visual Basic .NET, the biggest change is support for inheritance. Deriving a new class from an old one and picking up the functionality of the old class isn't possible in Visual Basic 6.0, so there is also no way to override only selected methods. This is a very significant change, but not because you have a burning need to create your own base classes and derive from them. The biggest value comes from being able to inherit the same framework classes used by programmers working in C#, C++, or any other Mirosoft .NET language. And if you do create inheritance-based frameworks yourself in Visual Basic .NET, any other Microsoft .NET programmer can use your frameworks. This puts Visual Basic .NET on equal footing with all the Microsoft .NET languages and breaks down the barriers that have isolated Visual Basic programmers in the past. Summary In this document, you learn about the differences between class inheritance and interface implementation. Inheritance supports the creation of hierarchical frameworks of increasingly specialized classes that share some code and also add their own customizations. Interfaces allow multiple unrelated classes to share predictable sets of methods and properties. Both interfaces and
Copyright - IT Engg Portal www.itportal.in 1 1

inheritance provide polymorphism, allowing generic procedures to work with many different kinds of objects. You also saw how object composition allows you to reuse and extend implementation code without inheritance, and how it can be combined with interfaces to support polymorphism. All these techniques enable you to create and revise complex software systems by helping you add new functionality, with minimal need to dig back into old working code.

1 2

Copyright - IT Engg Portal www.itportal.in

Você também pode gostar