Reputation: 9261
Here I came across this phrase:
Implementing a private interface is a way to force the definition of the methods in that interface without adding any type information (that is, without allowing any upcasting).
I'm finding it difficult to understand this. Can some one explain this for me?
Upvotes: 6
Views: 588
Reputation: 9261
I have investigated in to this issue and able to find some more information. The following is a practical example
The SaveInterface class is a type (i.e. a class with no implementation, all its methods are abstract). It has one public member function called SaveData(). The Document class from the initial solution now implements the SaveInterface type in a manner which keeps the SaveData() method from being accessible to clients of Document.
Notice that, in this solution, SaveHandler does not have a navigable association with the Document class. This has been replaced with a navigable association to the SaveInterface class. Since SaveData() is declared publicly in the SaveInterface class SaveHandler no need to be declared as a friend of the Document class.
Since the SaveHandler class is not a friend of the Document class it does not have the ability to change any of its private member variables or call any of its private member functions. So the encapsulation of the Document class has been preserved. The SaveHandler class no longer even needs to know about the Document class since it now depends on an interface called SaveInterface. This reduces the overall dependencies in the design and creates a potential for reuse.
Participants
Target (Document)
Client
Command
RequestHandler (SaveHandler)
created with a reference to the RequestInterface. implements the Command interface so the Target class can call the Execute() member function to perform the request.
in the motivating example, the SaveHandler class is used to create a separate thread of execution and then call a member function defined in the SaveInterface to actually save the data in the Document in the newly created thread.
RequestInterface (SaveInterface)
Known Uses
This pattern is used extensively in an embedded real-time environment at Xerox. It is employed in order to break the thread of execution in classes that perform various services for their clients.
For More info : http://www.objectmentor.com/resources/articles/privateInterface.pdf
Upvotes: 1
Reputation: 37645
Here is an example of private interfaces.
public class Main {
private interface Animal {
void makeNoise();
}
public static final class Cow implements Animal {
@Override
public void makeNoise() {
System.out.println("Moo!");
}
}
public static final class Sheep implements Animal {
@Override
public void makeNoise() {
System.out.println("Bah!");
}
}
public static void main(String[] args) {
List<Animal> animals = Arrays.asList(new Cow(), new Sheep());
for (Animal animal : animals)
animal.makeNoise();
}
}
From within the class Main
you can refer to an Animal
and call makeNoise()
on it. Therefore you can have a List
of Animal
s of different types and use a for each loop to call makeNoise()
on them all.
However, outside the class Main
this is not possible. You can have a Cow
or a Sheep
and call makeNoise()
on either, but the interface Animal
and the interface method makeNoise()
are invisible.
Upvotes: 5
Reputation: 54629
The examples in the linked article are a bit contrived and artificial (as already indicated by the odd names, A
, B
etc...). However, let's focus on the part of the quote that your question refers to:
"...without adding any type information (that is, without allowing any upcasting)."
The class may offer multiple (public or private) implementations of this interface. But the key point is:
Nobody will ever be able to figure out that they implement this interface.
Simply, because the interface is not public.
I tried to create an example showing a possible application case. Of course, it is still contrived, but may make the point more obvious. Consider you want to model a Tree
data structure, which consists of Node
objects. These can be InnerNode
objects (which have child nodes) or LeafNode
objects (which have no children).
Such a class could be implemented like this:
class Tree {
// The private interface
private interface Node {
List<Node> getChildren();
}
// Both are public implementations
public class InnerNode implements Node {
@Override
public List<Node> getChildren() {
return Arrays.<Node>asList(getLeafNode(), getLeafNode());
}
}
public class LeafNode implements Node {
@Override
public List<Node> getChildren() {
return Collections.emptyList();
}
}
// These return the concrete, public types
public InnerNode getInnerNode() { return new InnerNode(); }
public LeafNode getLeafNode() { return new LeafNode(); }
// This returns the private interface type
public Node getRootNode() {
// Both concrete types can be returned here,
// because they both implement the interface
return getInnerNode(); // Works
//return getLeafNode(); // Works
}
// This uses only the interface type
public void traverseNode(Node node) {
System.out.println("Traversing "+node);
for (Node child : node.getChildren()) {
traverseNode(child);
}
}
}
In an external main
method, you can observe the limitations imposed by the private interface:
public static void main(String[] args) {
Tree tree = new Tree();
// The public concrete types can be used
Tree.LeafNode leafNode = tree.getLeafNode();
Tree.InnerNode innerNode = tree.getInnerNode();
// The private interface can not be used from outside:
//Tree.Node node = tree.getRootNode();
// This is possible: The class only uses its
// own private interface here
tree.traverseNode(tree.getRootNode());
}
In this example, you can call traverseNode
, passing in the Node
that is returned by getRootNode
, regardless of whether this node is a InnerNode
or a LeafNode
. In the current version, this will print something like
Traversing Tree$InnerNode
Traversing Tree$LeafNode
Traversing Tree$LeafNode
If you changed getRootNode
to return a LeafNode
, then it would only print
Traversing Tree$LeafNode
To put it simply, and as the name "private interface" already suggests: You can use this in order to hide the fact that two classes share a common ancestor.
Upvotes: 1
Reputation: 40500
I think, the question is why you would want to "force" your own class implement anything? I mean, it's your class, if you want it to implement a method, just implement it. "Private INTERface" is just a misnomer. An interface is the view of your class that you want to expose to outside. Making it private serves no purpose whatsoever.
If you are asking about "package private" interfaces, that's kinda different, although not much. You might want sometimes to implement an interface, that is internal to your implementation and is not exposed to the outside. It is pretty hard (albeit, not impossible) to come up with an example where it would be useful though.
Upvotes: 0
Reputation: 311163
A private interface is a way to force a class to implement some methods, without publicly exposing that this interface is implemented - e.g., you won't be able to create a List<MyPrivateInterface>
and add instances of your class to it.
Upvotes: 0