Slice permits you to pass an interface by value:
process accepts and returns a value of type
ClassBase. This is not the same as passing
id<ClassBasePrx>, 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,
ClassBase and, hence, can be passed to and returned from the
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
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 described for the class mapping, 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.