Lambda the Ultimate

inactiveTopic The MultiJava Project
started 4/27/2002; 8:37:28 PM - last post 5/3/2002; 11:30:31 AM
Chris Rathman - The MultiJava Project  blueArrow
4/27/2002; 8:37:28 PM (reads: 1990, responses: 5)
The MultiJava Project
a backward-compatible extension to The Java Programming Language that supports open classes and symmetric multiple dispatch. An open class is one to which new methods can be added without editing the class directly. Multiple dispatch allows the method invoked by a message send to depend on the run-time types of any subset of the argument objects.

This project shares some of the same goals as AspectJ but is much less disruptive - trying to maintain modular reasoning in the process. I've been trying to get a feel for the language extensions but have been unable to get the external top level functions to be recognized as part of the base class.

In AspectJ terminology, Open Classes are similar in effect to Introductions. MultiJava, however, doesn't allow one to tack on method definitions or implementations to interfaces - strictly applying to classes. MultiJava doesn't have the concept of wildcards to apply the implementation to more than one class at a time. Also, MultiJava currently limits introduction to instance functions - not allowing introduction of state, constructors or static methods.

All in all, Open Classes are much more limited than the introduction framework provided by AspectJ. That said, MultiJava does have the advantage of providing multi-methods. The language allows dispatch on the argument types of the functions using the Type@VarName qualifier on qualifier in the parameters.
Posted to OOP by Chris Rathman on 4/27/02; 8:38:55 PM

Chris Rathman - Re: The MultiJava Project  blueArrow
4/30/2002; 10:31:23 AM (reads: 841, responses: 0)
Just a note to say that I did get the compiler to recognize the externally defined methods. Reading the notes, it seems you have to specify all the source files in one fell swoop in the compilation process. The multijava compiler (mjc) doesn't currently have the capability to infer all the classes that need to be compiled when looking at a single source file.

Anyhow, got it to work. Guess the biggest complaint I'd have is the inability to currently add state (i.e. properties) to the classes. In addition to adding methods, visitors often require further state information to achieve their aims.

On a different note, I started reading a little on IBM's implementation of HyperJ. Could just be an impression, but docs that come out of IBM are usually thorough. Unfortunately, they can also be torturous when you are trying to learn something from scratch - having to read a whole lot before you can accomplish the first thing. Frankly, I learn better with an early start - even if my knowledge is very incomplete.

After browsing through HyperJ, I left with the impression that the use of external files to make the connections (-hyperspace and -concerns) creates a whole language onto itself. Might be useful and tie a lot of the loose ends that are present in AspectJ, but the whole idea of Aspects is to try and simplify things which are common concerns. I don't know that creating a whole meta language to describe the interrelationships of concerns is the way to meet that goal. But then I admit that I gave up the pursuit of learning HyperJ out of frustration - so my opinion is based on incomplete information.

Brent Fulgham - Re: The MultiJava Project  blueArrow
5/2/2002; 1:20:35 PM (reads: 840, responses: 1)
I was initially interested in the idea of cross-cutting and weaving functionality, but after reading some of the posts on the 15% AOP solution thread I have changed my mind.

After living through a few years of code maintenance, I have come to truly appreciate the utility of strong typing and some form of assertion or contracts. I have spent more hours tracking down obscure bugs caused by buffer overflow, or one method sending improperly formatted data to another, etc. Large systems build with C and C++ are obviously particularly vulnerable to this.

On the other hand, I have also frequently been faced with the frustrating situation where a class is declared as final, even though I have a clear and present need to create an off-shoot differing only slightly from the parent class. I can't, so I must copy the code (if it's available) into my project and create a whole new set of objects to work with. This "cut-and-paste" reuse does little to boost productivity or reliability.

I don't believe any modern language should be without multimethods -- we have all seen Peter Norvig's write-up on how dynamic languages greatly simplify (or do away with) some common design patterns. So I am quite excited by MultiJava.

I also like the idea of Open Classes, which would seem to allow a more Lisp-like extensibility to Java. It would certainly be nice to avoid having to reinvent the wheel every time someone is overly facisct in their class definitions. :-)

andrew cooke - Re: The MultiJava Project  blueArrow
5/3/2002; 6:21:53 AM (reads: 886, responses: 0)
I'm probably stating the obvious here, but the problem you describe about final classes can (always?) be solved by delegation. The only problem, apart from the typing involved, is that the new class cannot be used in code already written for the old class. But that can be avoided by using interfaces appropriately in the original design (something that's easy to say, but not often done, of course).

Are your comments on not liking AOP and C/C++ maintenance related? If so, how (do aspects imply non-static typing)?

Finally, are open classes in MultiJava just because they come "for free" with multimethods? In other words - what do open classes (usefully) provide that inheritance doesn't (I can't think of a good example where you couldn't use inheritance - legacy code can't use the new methods, or it couldn't have been compiled before)?

Chris Rathman - Re: The MultiJava Project  blueArrow
5/3/2002; 7:29:58 AM (reads: 810, responses: 0)
Finally, are open classes in MultiJava just because they come "for free" with multimethods?
MultiMethods are the main emphasis of MultiJava, but to take full advantage of the technique it really requires that they allow new methods to be attached to existing classes (ala Class Categories in Objective-c). They are not a free part of the implementation - and they really need to work on Open Classes a bit more. I'd like to see them get closer to the level of AspectJ's flexibility with Introduction.

There is one important difference between AspectJ and MultiJava that I did not mention. AspectJ operates exclusively on files for which you have source code. You can not introduce methods for which the compiler does not have access to source code. AspectJ is a two way street, in that it will modify the target class when it sees fit.

MultiJava has a distinction between top level methods (i.e. introduced methods) that are internally defined and those that are externally defined. Internally defined functions are equivalent to defining the method directly within the class. So these would be equivalent in results for the compiler:

class MyClass {
   void myMethod() { }
}

and

class MyClass {
}
void MyClass.myMethod() { }

Although you're allowed to pull the methods out of the body of the class, the compiler generates the same code - all within the class being defined.

If, however, you define the top level method in an external file (must be named the same as the function myMethod.java), then mjc takes a totally different approach. A set of new classes are generated that are used by the classes that "include" that external definition. These classes do the delegation for you, similar to how you would go about doing a manual delegation. The advantage, of course, being that the class calling the included method calls just invokes them like they would if they really were part of the class receiving the message.

Brent Fulgham - Re: The MultiJava Project  blueArrow
5/3/2002; 11:30:31 AM (reads: 829, responses: 0)
To respond to Andrew's comment:

" .... the problem you describe about final classes can (always?) be solved by delegation. The only problem, apart from the typing involved, is that the new class cannot be used in code already written for the old class... "

Unfortunately, most of the times where you do wish to add functionality to an existing class, you are trying to interoperate with a world of code written with just the knowledge of the old class. As we all know, programs spend most of their lives in maintenance/extension mode -- where concepts like open classes and multimethods can really be a big productivity win.

The problem with delegation in my mind, is that Java's single-inheritence model makes it quite tedious and error-prone to delegate to internal classes in cases where you wish to be able to treat the new variant as an instance of the old class (e.g., to be stored as part of an existing collection or whatnot.)

Delegation becomes even harder when the original architecture did not anticipate this eventuality, leaving critical functions as protected visibility so you can't adequately wrap the class the way you need to.

As you point out, Interfaces are a good way around this. But again, you are forced to re-implement much of the code, since the interface is not permitted to provide implementations of the code.

So, you are correct that we can reach the result we need, the problem is that it involves a lot of tedious duplication of work, and a lot of potentially error-prone "instanceof" and "case" stuff to dispatch to the right object in these cases.

My concerns with AspectJ (note: Not AOP in general) are mostly based on Oleg's posting, in which he discusses the problem of "knowing" what order different tangled join-points are executed in (see his example on adding a "debugging" aspect.) Until this is clarified in some way, I don't see how we are gaining much through the use of constructs like those of AspectJ (though to be honest I have not played with them much either.)

My impression is that gains we get by weaving aspects across modules and classes may be significant, but the ambiguities introduced by weaving aspects into the same join point (in a procedural context) may make debugging and so forth difficult.

I'm happy to be proven wrong -- anyone with strong AspectJ feelings, please post and tell me to go dunk my head! :-)