PROPOSAL: Improved Support for Optional Object Behaviors at Runtime

Stefan Schulz schulz at e-spirit.de
Sun Mar 29 04:17:32 PDT 2009


I like this proposal a lot, as it would solve quite some problems with 
Inheritance and Delegation. Mozilla uses a similar approach (no Java 
though) where you query a specific interface for an object. In their 
case, it returns null, but a ClassCastException, as suggested by Derek, 
would be fine as well.

Maybe, I am burned a bit with respect to taking classes as parameters 
for such methods, though. As we have parameterized classes all over the 
place, I am quite sure that the need or desire will arise for asking for 
more specific "extensions" that also fulfill a classes generics (e.g., 
List<String>). It might be usefull to apply the Super Type Token 
approach as described by Neal Gafter in his blog. Hence, you would pass 
in a parameterized TypeReference object instead of a Class instance.

This approach would also solve another problem, mentioned by Derek: 
method clashes with existing classes. By introducing a new class, let's 
say java.lang.TypeReference<T>, the resulting signature for the methods 
to query (has) and retrieve (get) an extension will be new to any class, 
and compete only with those taking Object as parameter, which could 
never have been invoked with an instance of TypeReference before.

Reflecting on this, I am not sure, though, if Coin is the appropriate 
project for this change, as it is rather a JDK change than a language 
change. At least, I cannot see any support necessary from the language side.

Stefan

Alan Snyder schrieb:
> Improved Support for Optional Object Behaviors at Runtime
> 
> 
> AUTHOR: Alan Snyder
> 
> OVERVIEW
> 
> FEATURE SUMMARY:
> 
> This proposal would add a method to class Object to allow runtime access
> to optional object behaviors.
> 
> MAJOR ADVANTAGE:
> 
> As designs evolve and become more complex, it is useful to split out
> separable chunks of behavior whose support by an object might be optional.
> In current Java, the universally applicable technique for testing for and
> making use of optional behavior is the type cast. The type cast is limited
> by its tight coupling with the type hierarchy; as a result, because Java
> has single class inheritance, a class can not support an optional behavior
> defined by another class that is not already in its class hierarchy. In
> addition, because type casts cannot be simulated by an object, it is not
> compatible with delegation. For an object implemented by delegation to
> support optional behaviors using type casts, there would need to be one
> delegating class for each possible combination of optional behaviors.
> 
> This proposal defines a method on class Object that can be used in place
> of type casts to test for and access optional behaviors. This proposal is
> not constrained by the type hierarchy of the target object, because it
> permits the optional behavior to be implemented using a different (but
> related) object. In addition, the determination of the available behaviors
> can be made dynamically. Specifically, this proposal allows a class
> implemented using delegation to mimic the set of optional behaviors
> supported by its delegate, even if the delegate is replaceable.
> 
> MAJOR BENEFIT:
> 
> By adding a method to class Object, this feature can be supported by any
> class, even existing Java platform classes, with no additional changes to
> their class hierarchies. Because the feature is universally available, the
> use of type casts for this purpose can be deprecated.
> 
> This technique can be used to simply interfaces, or avoid making them more
> complex.
> 
> MAJOR DISADVANTAGE:
> 
> Any change to class Object freaks people out. This is the only change I
> can think of that is so obviously universal that it deserves to be in
> class Object.
> 
> ALTERNATIVES:
> 
> One alternative is to define this method in a new interface. This
> disadvantage of defining a new interface is that existing classes and
> interfaces would not support the method without themselves being changed.
> The other alternative is to add this method to classes and interfaces on
> an as needed basis. Either alternative forces programmers to use type
> casts in those cases where this method was not available. Also, new
> implementations of unchanged classes and interfaces would not be able to
> support this feature for existing clients of those classes and interfaces.
> 
> EXAMPLE:
> 
> Suppose a program wants to test an object "o" at runtime for an optional
> behavior defined by a class or interface "T". In current Java, the program
> could write:
> 
>         try {
>                 T t = (T) o;
>                 ... use t ...
>         } catch (ClassCastException ex) {
>         }
> 
> Using the proposed feature, the program would write:
> 
>         T t = o.getExtension(T.class);
>         if (t != null) {
>                 ... use t ...
>         }
> 
> The following examples are all hypothetical, but plausible to varying
> degrees. Note that many of them use instances of existing platform
> classes.
> 
>         // Test a list to see if it is observable, and get access
>         // to the observable methods.
> 
>         Observable o = list.getExtension(Observable.class);
> 
>         // Test a file to see if supports metadata, and get access
>         // to the metadata methods.
> 
>         FileMetadata fm = file.getExtension(FileMetadata.class);
> 
>         // Test file metadata to see if Mac OS file metadata is
>         // supported. Note that the file might be on another
>         // machine, so this call might succeed even on a non-Mac system.
> 
>         MacOSFileMetadata mfm = fm.getExtension(MacOSFileMetadata.class);
> 
>         // Test a file to see if it supports the new File API.
>         // Note that using this approach the new File API does
>         // not have to be an extension of the old API.
> 
>         java.nio.File nf = file.getExtension(java.nio.File.class);
> 
>         // Test a file to see if it is a directory, and get access to
>         // the directory methods.
> 
>         Directory dir = file.getExtension(Directory.class);
> 
>         // Test a file to see if it is a symlink, and get access to
>         // the symlink methods.
> 
>         Symlink s = file.getExtension(Symlink.class);
> 
>         // Test a file to see if it a directory and whether it provides
>         // read and update access to the directory contents using the
>         // List API (!).
> 
>         List<File> fs = (List<File>) file.getExtension(List.class);
> 
> DETAILS
> 
> The default definition in class Object would be:
> 
>         public <T> T getExtension(Class<T> c)
>         {
>                 try {
>                         return (T) this;
>                 } catch (ClassCastException ex) {
>                         return null;
>                 }
>         }
> 
> Thus, if not overridden, the method has the same effect as the type cast.
> Thus it can be used in place of type casts even on instances of existing
> classes.
> 
> Once this method is in place, programmers should be discouraged from using
> type casts for the purpose of testing for optional behavior.
> 
> SPECIFICATION:
> 
> JLS 4.3.2 would be changed to define this method.
> 
> I'm not aware of other changes.
> 
> MIGRATION:
> 
> It would be advisable to convert appropriate type casts to invocations of
> this method in existing code.
> 
> Once this method is available in class Object, other Java platform classes
> and APIs can be changed to take advantage of it.
> 
> COMPATIBILITY
> 
> BREAKING CHANGES:
> 
> No matter what name is chosen for this method, some existing program could
> fail to compile if it defines a method with the same name and signature
> but (say) a different return type. Methods with class parameters are
> presumably uncommon.
> 
> According to JLS 13.4.12, binary compatibility should not be broken
> because the method is public.
> 
> EXISTING PROGRAMS:
> 
> Existing classes automatically support this method to the same extent that
> they current support type casts for accessing optional behavior.
> 
> 
> 
> 



More information about the coin-dev mailing list