New page: By exposing a Java '''interface''' in an API one usually creates two sides of an API. One for clients that may call methods on instances assignable to that interf...
New page
By exposing a [[Java]] '''interface''' in an [[API]] one usually creates two sides of an [[API]]. One for [[ClientAPI|clients]] that may call methods on instances assignable to that interface and one for [[ProviderAPI|providers]] that may implement that interface. This is often not really desirable. Each of these [[API]] types has different [[evolution]] characteristics. Also the [[clarity]] of such interface methods may not be as clear as it could. More about this in [[ClarityOfAccessModifiers]] and [[ClarityOfTypes]].
Most common example of such ''interface'' with double purpose is ''java.lang.Runnable''. Everyone implements it, there is a lot of methods in [[Java]] standard libraries that also accept it. Another group of such interfaces includes almost all [[JavaBean]]s listeners. Implementing ''java.beans.PropertyChangeListener'' is example [[ProviderAPI]]. Almost everyone wrote such code at least once. Also, as [[JavaBean]]s specification is common, a lot of programmers also used the interface in [[ClientAPI|client]] way after adding following code into their classes:
<source lang="java">
public void addPropertyChangeListener(PropertyChangeListener l) { this.listener = l; }
public void removePropertyChangeListener(PropertyChangeListener l) { this.listener = null; }
protected final void fireChange() {
this.listener.firePropertyChange(new PropertyChangeEvent(this, null, null, null));
}
</source>
Interfaces contain '''public''' methods which are know to have [[ClarityOfAccessModifiers|multiple meanings]] as such they are often subject to double use. One can prevent that by usage of [[ImplementOnlyAbstractClasses]], yet it may not be always the preferred solution.
=== Implement Only Interface ===
On the other hand, the algorithm to redesign multi meaning classes into [[ClarityOfTypes|types with clear meanings]] suggests to use create '''interface''' ''Provider'' and claims that such interface methods have just a single meaning. Can '''interface''' have just a single meaning? [[Talk:ClarityOfTypes|parren questioned that]]:
The ''Provider'' '''interface''' is a '''public''' interface residing
within a public class. I can implement this interface and throw it
around at will. For that reason, instances of the interface are
accessible to clients of the API. For the same reason, they say to me:
''implement me and do whatever you want with me, including call me''.
Sort of true, but I still insist that the interface methods have only single meaning within its [[API]]. Imagine there is thousands users of following [[API]]:
<source lang="java" snippet="sidemeanings.Mixed.Clean.Factory"/>
These usages are packaged in their own modules (independent compilation units) and they do not know about each other. They only compile against and use the above [[API]]. Each of them can create a class that implements the ''Provider'' interface. However the only useful thing that can be done with such class, is to create its instance and pass it into the ''NonMixedFactory.create'' method. But that method keeps the instance for private purposes and does not let any other user of the [[API]] to access it.
There is no way some other module using [[API]] could get access to instance of such ''Provider'' implementation. As such the ''Provider'' methods has just a single meaning: ''implement me!''.
=== Silly Usage ===
One might argue, that the same module (e.g. compilation and runtime unit) can start to access its own implementation:
<source lang="java">
class MyProvider implements Provider { ... }
Provider p = new MyProvider();
p.toBeImplementedBySubclass();
</source>
True, this is possible use. More ''misuse'' than a use however. One could call the ''MyProvider'' methods directly by declaring the variable to be of ''MyProvider'' type. So the usage of ''Provider'' in this example is unnecessary.
However even with ''Provider'' variable, the meaning of ''Provider'' in the ''NonMixedFactory'' [[API]] is still clear. That fact that one module decides to internally misuse it can't affect that.
=== Reexporting API ===
Possible problem may arise when the ''MyProvider'' class is part of [[API]] of its module. Then other modules can use it and indeed, can also call its methods. Then the clarity of the ''Provider'' methods lost. However this is not fault of the original ''NonMixedFactory'' [[API]], but fault of this new one which re-exports the interface.
The original [[API]] has still its [[clarity]], but the whole system's single meaning is compromised by additional [[API]]s. There is not much the author of the original [[API]] can do about this, then hope others won't do silly things like this or using [[ImplementOnlyAbstractClass]] pattern. I personally prefer to hope.
=== By Passing ===
Last way for the ''Provider'' implementation to get into hands of other modules is escaping through some other [[API]]. For example one could:
<source lang="java">
class MyPanel extends JPanel implements NonMixedFactory.Provider {
...
}
</source>
Then other modules can get access to such JPanel through AWT component hierarchy and use '''instanceof''' check to safely get foreign ''Provider'' implementation which can then be ''called''.
However this the fact that there is some ''JPanel'' that can be cast to ''Provider'' is an example of [[APITypes|runtime API]]. As such this means the module providing ''MyPanel'' is also providing additional [[API]] and we are in similar to situation analysed in ''Reexporting API'' section.
[[Category:APIDesignPatterns]]
[[Category:APIDesignPatterns:Clarity]]
[[Category:APIDesignPatterns:Creational]]