public class Twisted { private final String name; Twisted(String name) { this.name = name; } private String name() { return name; } private void reproduce() { new Twisted("reproduce") { void printName() { System.out.println(name()); } }.printName(); } public static void main(String[] args) { new Twisted("main").reproduce(); } }
Solution 92: Twisted Pair
A superficial analysis suggests that the program shouldn't
compile. The anonymous class inside reproduce TRies to invoke the
private method name from the class Twisted. One class can't
invoke a private method of another, can it? If you tried to compile the program,
you found that it compiles without a hitch. Within a top-level type—in this
case, Twisted—all the local, inner, nested, and anonymous classes can
access one another's members without any restrictions [JLS 6.6.1]. It's all one
big happy family.
With that understanding, you might expect the program to print
reproduce, because it invokes printName on the instance
new Twisted("reproduce"), which passes the string "reproduce"
to its superclass constructor to be stored in its name field. The
printName method invokes the name method, which returns the
contents of this field. But if you ran the program, you found that it prints
main. Now why would it do a thing like that?
The intuition behind this behavior is that private members are never inherited [JLS 8.2]. In
this case, the name method is not inherited into the anonymous class in
reproduce. Therefore, the printName invocation in the
anonymous class must refer to the method in the enclosing ("main")
instance rather than the current ("reproduce") instance. This is the
smallest enclosing scope that contains a method of the correct name (Puzzles 71 and 79).
This program violates the advice of Puzzle 90: The anonymous class inside
"reproduce" is both an inner class of Twisted and extends it.
This alone is sufficient to make the program unreadable. Throw in the complexity
of invoking a private superclass method, and the program becomes pure
gobbledygook. This puzzle serves to reinforce the lesson of Puzzle 6: If
you can't tell what a program does by looking at it, it probably doesn't do what
you want. Strive for clarity.
No comments:
Post a Comment
Your comments are welcome!