A programmer new to object-oriented programming in Microsoft Visual Basic might assume that all that is required to pass an object by value is to include the
reserved word in a function declaration. For example:
One could mistakenly
that if the function caller passed in a Bar object that the Visual Basic compiler would create a copy of the object. The function code block could then manipulate the copy without
the original. For example:
The value of
changes in the calling program because passing an object by value actually
a reference to the object. For an explanation of this functionality, refer back to Chapter 2.
along the same lines is that if a class defines only a Property Get procedure to return an object and not a Property Set procedure, the class property is read-only. For example:
One might then assume that the Visual Basic compiler will return a copy of the Bar object when the
Property Get procedure is called, and whatever the caller does to it has no effect on the original. For example:
In both of the previous source code examples, a copy of an object reference is returned—not a copy of an object. To review the explanation provided in Chapter 2, an object variable in Visual Basic contains a reference to an object, not the object itself. Therefore, when an object variable is passed by value, a copy of the object variable is created that references the same object. Hence actions performed on all copies of an object variable affect the same object.
The Object By Value design pattern described in this chapter enables you to pass an object by value—passing a copy of the object rather than the object reference—by writing the object's state to a data stream, passing the data stream to the recipient process that constructs a copy of the object, and updating the new object's state from the data stream. This will produce an exact copy of the original object in the recipient process's address space.
The Object By Value design pattern
or returns an object by value from one function process to another, resulting in the receiving process obtaining a copy of the object rather than a copy of an object reference.
Use the Object By Value design pattern in the following circumstances:
To pass or return a copy of an object to a caller
This will protect the original object from unwanted state changes. For example, you can modify the property values of an object that is passed or returned by value without
the original object.
To pass or return a copy of an object from one process to another
This allows the recipient process to fully benefit from the services
by an object without having to incur the performance cost usually associated with
object interaction. When a COM object is created in the client process, the client directly references a memory address in its process space, resulting in immediate method invocation. COM objects created outside the client process suffer from significantly slower response times because a client process cannot reference the memory addresses of objects in other processes. Instead COM interposes and creates a proxy object in the client process that the client references directly in memory. When the client invokes a method on the object, a procedure known as marshaling occurs: The proxy object packages the request into a
data packet and forwards the request to a stub object that unpackages the request and invokes the method on the real object. The reverse occurs if the method has a return value or has parameters that are passed by reference. To avoid the major performance hit involved in marshaling data across process boundaries you can create a copy of the object in the client process. All object method invocations will then happen directly on the local copy of the object.
To pass or return a copy of an object between dissimilar object systems
This task is difficult to accomplish without using the Object By Value design pattern. For example, you might want to create the original object in Visual Basic and then pass a copy of it to a Java application. Java and Visual Basic have different semantics and syntax for defining an object, but, providing both sides agree on how to interpret a data stream, it's possible to "re-hydrate" an object created in one language platform in another.