friendcode.
Java by default restricts the friends of a class to those classes that are in the same package. If there is a functionality that you want share just among classes in the same package, use package-private modifier in definition of a constructor, a field or a method and then it will remain accessible only to friends
.
Sometimes however it is more useful to extend the set of friends to a wider range of classes - for example one wants to define a pure API package and put the implementation into separate one. In such cases following trick can be found useful. Imagine there is a class item:
public final class api.Item { /** Friend only constructor */ Item(int value) { this.value = value; } /** API method(s) */ public int getValue() { return value; } /** Friend only method */ final void addListener(Listener l) { // some impl } }that is part of the API, but cannot be instanitated nor listened on outside of the friend classes (but these classes are not only in api package). Then one can define an
Accessor
in the non-API package: public abstract class impl.Accessor { public static Accessor DEFAULT; static { // invokes static initializer of Item.class // that will assign value to the DEFAULT field above Class c = api.Item.class; try { Class.forName(c.getName(), true, c.getClassLoader()); } catch (ClassNotFoundException ex) { assert false : ex; } assert DEFAULT != null : "The DEFAULT field must be initialized"; } /** Accessor to constructor */ public abstract Item newItem(int value); /** Accessor to listener */ public abstract void addListener(Item item, Listener l); }with abstract methods to access all
friendfunctionality of the
Item
class and with a static field to get the accessor's instance. The main trick is to implement the Accessor
by a (non-public) class in the api
package: final class api.AccessorImpl extends impl.Accessor { public Item newItem(int value) { return new Item(value); } public void addListener(Item item, Listener l) { return item.addListener(l); } }and register it as the default instance first time somebody touches
api.Item
by adding a static initializer to the Item
class: public final class Item { static { impl.Accessor.DEFAULT = new api.AccessorImpl(); } // the rest of the Item class as shown above }Then the friend code can use the accessor to invoke the hidden functionality from any package:
api.Item item = impl.Accessor.DEFAULT.newItem(10); impl.Accessor.DEFAULT.addListener(item, this);
只有注冊用戶登錄后才能發表評論。 | ||
![]() |
||
網站導航:
博客園
IT新聞
Chat2DB
C++博客
博問
管理
|
||
相關文章:
|
||