Java OO just isn't dynamic enough

jdavidb on 2008-02-20T21:59:14

As near as I can tell, it is not possible to write a method which takes an instance of class A and modifies it such that it is now an instance of subclass A'. This is quite distressing. I can write a class B that HAS-A instance of A, and delegates to it, but I cannot write a class A' that IS-A instance of A, where the instance of A' actually IS, in fact, the instance of A I started with. I can write a class B with a constructor that takes an instance of A and copies all the public information out of it and tries to mimic the A it received, but that's still not going to work for objects that somebody else's API gives me. And of course if I were the author of class A I could make its internals much more exposed to facilitate this, but I'm not, and if I were the author of the API that's giving me an A I could change the method or write a new one that gives me an A', but I'm not, so I can't.

I hardly ever touched such dynamic features in Perl, but I knew they were there when I needed them. For some strange reason I've wound up doing or attempting far more dynamic stuff like this with Java than I ever did with Perl.

Of course, being able to do this is not necessarily a good idea, but if I were in Perl I'd write a nice constructor method to encapsulate taking an object of the superclass and reblessing it into the subclass, and it'd be mostly clean other than the evil magic inside that constructor. Java just forbids such witchcraft altogether.

BTW, I learned about mixins from prompting here, within the last 30 days, and already I miss those, too, even though I've never had them. :)


Java

Ovid on 2008-02-21T08:31:01

My first realization that I really wasn't "thinking" Java was when I wanted a dispatch table whose keys were anonymous subs closing over values determined at runtime. I wound up creating a class hierarchy and used polymorphism to handle the dispatching. Instead of having all of my logically connected behavior in one place, I wound up spreading it across multiple classes which were created solely for the purpose of handling this dispatching. Being forced to shoehorn everything into "one-size-fits-all-OO-shoes" sucks :(

Re:Java

jdavidb on 2008-02-21T16:34:09

There's actually a semi-decent way to handle some of that. You define an abstract class (or interface) with the method you want to be able to call. Then, you define anonymous inner subclasses of that class:

public abstract DispatchInstance {
public abstract void processIt();
}

class OtherClass {
DispatchInstance[] table = new DispatchInstance[] {
  new DispatchInstance() {
    public void processIt() {
      int value = val1;
    }
  },
  new DispatchInstance() {
    public void processIt() {
      int value = val2;
    }
  },
  ...
}

Not sure if that would have fit the bill or not, but it's easier than making explicit subclasses for every single one of those!

Re:Java

Ovid on 2008-02-21T17:20:23

Wow. Ugly as hell, but yet, much better than what I wrote. Reminds me of how some Java programmers argue that they don't need closures because they have anonymous inner classes. It's true, I suppose, but it's an awful lot of grunt work.

As you can see, I'm not much of a Java hacker :)

Re:Java

jdavidb on 2008-02-21T19:25:30

Well, I just completed a class where I actually had to use this technique, and I'll testify that I definitely would've rather had something else. And you're right; it is ugly. In my case I don't think it was closures I was looking for, but I'm not sure what it was.

The good news is I replaced it with something even more amazing.

potential mixin help

lachoy on 2008-02-22T04:36:59

qi4j, once it's out, might prove verrrry interesting