The Fundamentals of COM

A modem follows a standard—such as v.32bis—when communicating with another modem. The standard defines a protocol for the conversation between the two modems. Any modem that supports a given communications standard will be able to talk to another modem that supports the same standard. This communication standard defines the behavior of a compliant modem, but it doesn’t specify how a given modem is to generate that behavior. COM is a standard that defines the behavior of software components.

In 1996, Microsoft added support for COM to Java, through its own Microsoft Internet Explorer and via add-ins for products produced by other vendors. Java vastly simplifies COM programming by handling many details internally. Support for COM is implemented within the virtual machine, not in the language itself, so many of the details are hidden from the Java developer. Not only does this make your job as a Java programmer easier, but also it allows you to avoid some of the more confusing and error-prone aspects of using COM. If you’ve worked with COM in C++, you’ll find that working with it in Java requires a bit of rethinking and adjusting, since you won’t be handling many of COM’s intricacies.

COM became part of Windows-based programming with the introduction of OLE in the early 1990s, but it became a common term only when the Internet spawned ActiveX in 1996. COM, the underlying foundation of OLE and ActiveX, is a standard that allows independent software objects to communicate with one another. Whereas OLE focuses on building complex documents from objects that are linked to various components, ActiveX is aimed at developing small, downloadable program components for the Internet. ActiveX is not a subset of OLE; rather, it is a different way of using COM technology to build software components. Another name for COM components is Automation objects, which refers to their use in automating tasks inside documents and on web pages.

A software component uses COM to declare one or more interfaces; you can think of an interface as a contract presented by a server and accepted by a client. Server and client might be—and probably are—separate processes, and they might even be located on different machines. However, a single process can be both a server and a client, exposing functions through interfaces and using other components simultaneously. A COM object can be an application, a dynamic-link library (DLL), a visual control, or any other piece of executable code that supports the COM standard.

COM describes the format servers must follow to express their interfaces and how clients locate and communicate with available servers. Think of COM as another way of implementing the object-oriented principles I presented in previous chapters. COM embodies a central principle of object-oriented programming, encapsulation: A COM component is accessible only through the methods that are declared in the interfaces it exports. The mechanism a given component uses to implement those methods internally is immaterial; COM concerns itself only with expressing interfaces in a standard fashion so that all compliant components can interact.

In terms of COM, the word interface refers to a set of related methods that are exposed by a component. An exposed method is a method that an object makes available for calling by an outside agent; you can think of an exposed COM method as similar in principle to a public method in a Java class. In fact, a COM interface is much like a Java interface. When a component supports a given COM interface, it supports all methods defined by that interface. The interface definition declares the terms of a contract between a server and a client, but it doesn’t say how those terms will be executed. That’s the job of the interface implementation, which is completely hidden from all client applications. An interface implementation can be written in any language, using any algorithms; the details of the implementation are hidden from the client. An interface is not an object; it is a pointer to a table of method pointers. A component will provide a table of method pointers for each interface it supports; all communication with the component takes place through these method pointers. The methods exposed via an interface are strongly typed, that is, a call to a COM method will generate a compile-time error if the call parameters and return value don’t strictly match the interface definition.

A table of interface method pointers is much like a C++ virtual function table. Such a table is also used by Java to implement all of its methods. This is one reason why Java is eminently suited to writing COM applications: many features of COM correspond to features of Java classes. But don’t confuse a COM interface with a Java interface; the former defines a contract between COM components, and the latter declares a set of methods and fields to be implemented by subinterfaces. Nor should you confuse a COM class with a Java class. The sidebar “How a COM Object Differs from a Java Class” outlines their differences.

How a COM Object Differs from a Java Class

© 1997 by Scott Ladd. All rights reserved.