The virtual field pattern
Brenden Towey
brendentowey at gmail.com
Thu Aug 9 12:06:49 PDT 2012
(Resending, apologies to Yuval for my clicko.)
Yes, more boilerplate to fix things which should not be broken in the
first place. Reminds me a bit of generics. The problem is the
boilerplate obscures what should be a simple idea: private inheritance,
private implementation. It's "the vertical problem" where too much code
gets in the way of straight-forward ideas.
Anyway, I'm not worried about malicious code so much as I am good
practice. Encapsulation is a core principle of object oriented
programming, and the ability to hide complexity, in the form of internal
implementation, from users. If people want to be malicious, they can
muck with the SercurityManager policy and reflection. The capability to
be malicious exists now. It is simply clearly demarcated as beyond the
pale by the extreme measure one must take to do it.
Public methods require no such measures, and in fact are they are used
to indicate methods which the user should feel free to call. It's a
totally different mind-set.
I'm don't know what "should" happen with protected methods in
interfaces, but the usefulness of the virtual field pattern decreases
markedly if the delegate() method must be public. I'd hate to see a
repeat of generics, where it seems "practicality" in the short term won
out, and is now seen as a defect by some. Especially vis-a-vis other
implementations available in other languages.
On 8/9/2012 10:41 AM, Yuval Shavit wrote:
> It's not too hard to hide that, though it takes a bit of boilerplate.
> It would involve not just implementing VirtualList<T>, but doing so in
> a way that returns, as a List<T>, an inne/list class which is itself a
> VirtualList<T> but adds the invariants:
>
> public class EchoList<E> implements DelegatingList<E> {
>
> @Override
> public List<E> getDelegate() {
> return delegate;
> }
>
> private List<E> delegate = new InnerList<E>();
> private class InnerList<E> implements DelegatingList<E> {
>
> @Override
> public List<E> getDelegate() {
> return innerDelegate;
> }
>
> @Override
> public boolean add(E e) {
> System.out.println("invariant says hello to " + e);
> return super.add(e);
> }
> private List<E> innerDelegate = new ArrayList<E>();
> }
> }
>
> So now, while it's true in some sense that you've exposed your
> implementation via EchoList.getDelegate, you've exposed it in a way
> that can only easily be accessed as a List<E> which acts exactly like
> your EchoList<E>.
>
> Someone could get around this by casting getDelegate()'s result to a
> DelegatingList<E>, at which point they can access the underlying List
> without triggering your invariant -- so this is not secure if you're
> worried about malicious users. The boilerplate is also not pretty.
>
> Once/if interfaces get protected methods, one could just make
> DelegatingList.getDelegate protected (at the cost of binary
> compatibility, right? would that be significant?).
>
> On Thu, Aug 9, 2012 at 1:19 PM, Brenden Towey <brendentowey at gmail.com
> <mailto:brendentowey at gmail.com>> wrote:
>
> I was thinking that a practical use for this pattern would be, for
> example, the Collections API, like java.util.List:
>
> package java.util;
>
> public interface VirtualList {
>
> List getDelegateList();
>
> boolean add( Object o ) default {
> return getDelegateList().add( o );
> }
> ...etc.
> }
>
> (Generics omitted for brevity.) Definitely not a package-private
> interface. Nor would I personally guess that the more interesting
> uses
> of the virtual field pattern would be "probably" package-private
> either. I'd guess they're all public, myself.
>
>
>
> On 8/9/2012 10:07 AM, Olexandr Demura wrote:
> > No, its not, since VirtualSomething extends P.
> > So, its probably package-private interface - will not leak.
> >
>
>
>
More information about the lambda-dev
mailing list