1

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!

4

2 回答 2

1

你可以看看Annotation Processing Tool。它允许您在编译代码时进行编译时注释并产生警告/错误。

于 2013-05-23T11:54:06.220 回答
0

我认为没有一种干净的方法可以做到这一点。请考虑另一种设计。

如果您希望 A 类仅服务于 B 类及其子类,请将 A 类定义为 B 的内部类并为其赋予受保护的访问修饰符。

于 2013-05-23T10:18:26.010 回答