Please log in.
Before you can vote, you need to register. Please log in or create an account.
Computer: Programming Language
Java Filters   (+1)  [vote for, against]
Make wrapping already-created objects trivially easy to do.

Java's current scheme of using Classes and Interfaces to handle objects is generally adequate, but there's one specific scenario where it's a royal pain: when you've got an already-instantiated object of some other class (possibly generated by a factory method of some other class beyond your control) that needs to be thinly wrapped to filter data passing through it.

Sure, you can create a new class that has the already-created object as a private member, then implement the object's entire interface and delegate everything to the object... but if you spend even a minute thinking about where this is the most useful (say, JDBC-related classes implementing ResultSet, Statement, Connection, etc) and look at the sheer number of methods required by most of 'em, something that SHOULD be trivially easy to do quickly becomes a 30-90 minute exercise in manual labor.

Worse, if you're wrapping an object that some other method actually NEEDS to access as its native type above and beyond the generic interface (say, OracleConnection vs Connection), the scheme quickly starts to fall apart and get ugly... even if you implement the subclass' methods, the signature will still be wrong unless you try to extend that class.

What I propose is a lightweight construct called "filter" to sit proudly alongside "interface" and "class" (or, more accurately, cover them with duct tape *grin*). "Filter" methods would have three scopes:

* public methods with the same name and signature as the wrapped object would be called instead of that object's methods. The wrapper method could access the wrapped class' method using "wrapped." the way a subclass uses "super.".

* protected methods with the same name and signature as the wrapped object would ONLY be called if the wrapped object were explicitly cast to the wrapper type. In other words, naive clients call the original method, knowing clients can call the wrapped one.

* private methods, as expected, can only be called by the wrapper's own methods.

public filter FooWrapper {

// public methods override the wrapped method outright

public int someMethod(String value) {

// do something first

return wrapped.someMethod(internalMethod(value));

}

// protected methods override wrapped method ONLY if object explicitly cast to wrapper

protected String toString() {

return "value returned when wrapped object explicitly cast to wrapper";

}

// private methods can only be called by the wrapper

private String internalMethod(String value) {

return "foo-" + value;

}

}

Want to make some existing object created by somebody else's factory method implement some particular interface (say, Observer) after the fact?

public filter Chaperone implements Observer {

// implementation of Observer interface that calls one of

// the wrapped object's methods when the object it's observing fires off a message...

}

FactoryMadeObject theObject = someObject.createFactoryMadeObject();

Chaperone sentry = new Chaperone().wrap(theObject);

// voila!

theObject.getClass().getName() --> FactoryMadeObject

(theObject instanceof FactoryMadeObject) == true

(theObject instanceof Observer) --> true

(theObject instanceof Chaperone) --> true

theObject.getWrapper().getName --> "Chaperone"

theObject.getWrappers() --> List of wrappers, from the outermost to the Class of the wrapped object.

OK, I'll admit this isn't entirely a new idea. In other languages, this would be classified as a tiny subset of multiple inheritance... something Gosling apparently hated with a passion and was determined to prohibit in any form. Still, I think that something along the lines of this idea would probably get a standing ovation at a Java programmer's conference (followed moments later by angry, livid tirades from the tiny handful of purists who oppose the sullying of Java's academic purity with something as lowbrow as multiple inheritance in any form)...
-- miamicanes, Jul 26 2003

Dynamic inheritance http://burks.bton.a...gdocs/oofaq/s1a.htm
Dynamic inheritance is very much like what you describe [Chvorthq, Jun 09 2006]

Sure you can (usually) subclass and/or implement the whole interface. But it's a pain. And if you're trying to wrap an object that's exposed to YOU as an interface, but created "higher up" as a concrete object with more functionality and ultimately passed to a method that expects it to be an object of that class, you have no choice but to break the facade and pass the raw object to that method rather than the neatly wrapped object (because otherwise, an instanceof test of your wrapper will fail).
-- miamicanes, Jul 27 2003


Just to add another specific instance where a "wrapped" construct would make life a lot easier: reading/writing BLOB fields under Oracle when using a connection pool besides Oracle's own, like DBCP. Yes, you *can* explicitly configure DBCP to permit access to the raw underlying object, extract the raw OracleConnection from the DBCP wrapped connection, use it directly, then nullify the local reference to the raw connection and "close" the wrapped one... but it's a pain in the ass. It would be *so* much nicer if DBCP's wrapper could be transparent to classes downstream and not inhibit the object's inherent Oracle-ness unless it *intentionally* set out to do so.
-- miamicanes, Jan 26 2004


Just got out of bed, and while the kettle heats, here I sit, thinking someone had just invented something novel to strain my coffee through....sigh.... as one passes through the filter of life, one must strain to measure up to all the disappointments.....
-- normzone, Jan 26 2004


That's a good idea, but it looks a lot like dynamic inheritance (see link). That feature allows you to write a function that takes an object and returns, in effect, a new object that's a dynamically generated subclass of the argument.

Another way to think of it is that you can just add, remove, or modify methods at runtime.
-- Chvorthq, Jun 09 2006



random, halfbakery