views:

189

answers:

2

I am trying to make a View class that provides a Horizontal or Vertical layout depending on how it is created. I'm using a delegate to achieve this.

class View extends Manager {
    private Manager mDelegate;

    public View(Manager inDelegate) {
        mDelegate = inDelegate;
        // the delegate is the only child of "this" manager.
        super.add(mDelegate);
    }

    public void add(Field f) {
        // all other children go into the delegate.    
        mDelegate.add(f);
    }

    // other methods that also delegate

}

When I instantiate a View object I pass in a Horizontal or Vertical field manager and then delegate calls to that. This is kinda what the Screen class does in blackberry.

Actually I am looking at the blackberry docs for Screen to see what calls it delegates (so I can emulate that) and I notice calls like this in Screen...

protected boolean keyChar(char c, int status, int time)

Delegates key generation event to the controlled field with focus. This method invokes Manager.keyChar(char, int, int) on this screen's delegate manager.

So then it immediately dawns on me, how in the world are they calling a protected method on the screen's delegate? Or are the docs wrong and this method isn't delegated?

Anyone know how they accomplish this?

A: 

Reminding myself what protected means:

A protected method can be called by any subclass within its class, but not by unrelated classes.

This doesn't directly answer your question, but could you extend Screen (API here) instead of Manager and then call super(mDelegate) in your constructor? Then presumably whatever magic is necessary will just work?

Aside from that I would just suggest you try it and see if you can override the supposedly protected method!

Dan J
A: 

I managed to work out a solution to this problem with help from some other SO questions.

My solution is to create an interface that provides the public access points for the protected methods and then subclass the Manager class and mix in that interface. The public method will then call its super's protected method.

Then the View class is then passed one of these Manager subclasses.

public interface ManagerDelegate {
    Manager asManager();
    // Provide public access points to any protected methods needed.
    void doProtectedMethod();
}

public HorizontalDelegate extends HorizontalFieldManager implements ManagerDelegate {
    public Manager asManager() {
        return this;
    }
    public void doProtectedMethod() {
        // call the Manager's protected method.
        protectedMethod();
    }
}

public VerticalDelegate extends VerticalFieldManager implements ManagerDelegate {
    public Manager asManager() {
        return this;
    }
    public void doProtectedMethod() {
        // call the Manager's protected method.
        protectedMethod();
    }
}

public class View extends Manager {
    private final ManagerDelegate mDelegate;

    public View(ManagerDelegate inDelegate) {
        mDelegate = inDelegate;
    }

    protected void protectedMethod() {
        // Call into our delegate's public method to access its protected method.
        mDelegate.doProtectedMethod();
    }

    public void publicMethod() {
        // For public delegated methods I can just get the Manager instance from
        // the delegate and call directly.
        mDelegate.asManager().publicMethod();
    }
}
Maven