I have a Java problem for which I can't find an answer: I have a class A containing a method a() that should only be called from a class extending class B. For the moment, the best solution I could find is the one below:
Class callerClass = Reflection.getCallerClass(2);
if (!B.class.isAssignableFrom(callerClass))
throw new InvalidMethodCallException("A.a", B.class.getName(), callerClass.getName());
With InvalidMethodCallException
being an exception of my own.
However, I am not completely satisfied with my solution because of the fact that the call is made at runtime. Instead, I would want to declare in a()
that only B
should have access to it, but make this is checked at compilation time, since reflection is a costly process.
Do you know a proper way to do so ?
Thank you for your help.
Edit: Additional information
An easier example is that I don't want the user to call the method connect(port1, port2)
in class Edge
, but instead to call the method addEdge(edge, port1, port2)
from the Graph
class, because the graph also has to remember what edges if has inside.
Here is my code from class Graph
:
public void addEdge (Edge edge, Port firstPort, Port secondPort)
throws DuplicateEdgeInGraphException, AttachedNodeNotInGraphException, GraphDescriptionModelException
{
// Must not appear in the graph
if (this.edges.contains(edge))
throw new DuplicateEdgeInGraphException(edge);
// The nodes attached to the ports must be in the graph
if (!this.nodes.contains(firstPort.getNode()))
throw new AttachedNodeNotInGraphException(firstPort);
if (!this.nodes.contains(secondPort.getNode()))
throw new AttachedNodeNotInGraphException(secondPort);
// We connect the edge and add it
edge.connect(firstPort, secondPort);
this.edges.add(edge);
}
And from class Edge
:
public void connect (Port portOne, Port portTwo)
throws InvalidMethodCallException, WrongPortsDirectionsException, WrongPortsSizesException, GraphDescriptionModelException
{
// We check the reserved method call
Class callerClass = Reflection.getCallerClass(2);
if (!Graph.class.isAssignableFrom(callerClass))
throw new InvalidMethodCallException("Edge.connect", Graph.class.getName(), callerClass.getName());
// We check the directions of the ports
if ((portOne.isInputPort() && !portOne.isInputOutputPort() && !portTwo.isOutputPort())
|| (portTwo.isInputPort() && !portTwo.isInputOutputPort() && !portOne.isOutputPort())
|| (portOne.isOutputPort() && !portOne.isInputOutputPort() && !portTwo.isInputPort())
|| (portTwo.isOutputPort() && !portTwo.isInputOutputPort() && !portOne.isInputPort()))
throw new WrongPortsDirectionsException(portOne, portTwo);
// We check the sizes of the ports
if ((portOne.isInputPort() && !portOne.isInputOutputPort() && portOne.getSize() < portTwo.getSize())
|| (portTwo.isInputPort() && !portTwo.isInputOutputPort() && portTwo.getSize() < portOne.getSize())
|| (portOne.isOutputPort() && !portOne.isInputOutputPort() && portOne.getSize() > portTwo.getSize())
|| (portTwo.isOutputPort() && !portTwo.isInputOutputPort() && portTwo.getSize() > portOne.getSize())
|| (portOne.isInputOutputPort() && portTwo.isInputOutputPort() && portOne.getSize() != portTwo.getSize()))
throw new WrongPortsSizesException(portOne, portTwo);
// We avoid similar edges
for (Edge portOneEdge : portOne.getConnectedEdges())
if (portOneEdge.getOppositePort(portOne).equals(portTwo))
throw new SimilarEdgeAlreadyExistsException(portOneEdge);
// Ports' attributes
portOne.getConnectedEdges().add(this);
portTwo.getConnectedEdges().add(this);
// Attributes
this.portOne = portOne;
this.portTwo = portTwo;
}
Hope this helps understanding the problem.
Edit: Thanks to everyone!