Note that process accepts and returns a value of type
ClassBase. This is
not the same as passing a
ClassBase*, which is a
proxy to an object of type
ClassBase that is possibly remote. Instead, what is passed here is an
interface, and the interface is passed
by value.
The immediate question is “what does this mean?” After all, interfaces are abstract and, therefore, it is impossible to pass an interface by value. The answer is that, while an interface cannot be passed, what
can be passed is a class that implements the interface. That class is type compatible with the formal parameter type and, therefore, can be passed by value. In the preceding example,
SomeClass implements ClassBase and, hence, can be passed to and returned from the
process operation.
The Objective-C mapping maps interface-by-value parameters to ICEObject*, regardless of the type of the interface. For example, the proxy protocol for the
process operation is:
This means that you can pass a class of any type to the operation, even if it is not type-compatible with the formal parameter type, because all classes derive from
ICEObject. However, an invocation of
process is still type-safe at run time: the Ice run time verifies that the class instance that is passed implements the specified interface; if not, the invocation throws an
ICEMarshalException.
Passing interfaces by value as ICEObject* is a consequence of the decision to not generate a formal protocol for classes. (If such a protocol would exist, the formal parameter type could be
id<ProtocolName>. However, as we mentioned on
page 602, a protocol would require the implementation of a class to implement all of its operations, which can be inconvenient. Because it is rare to pass interfaces by value (more often, the formal parameter type will be a base
class instead of a base
interface), the minor loss of static type safety is an acceptable trade-off.