This program involves the interaction of two classes in
different packages. The main method is in class hack.TypeIt.
What does the program print?
package hack; import click.CodeTalk; public class TypeIt { private static class ClickIt extends CodeTalk { void printMessage() { System.out.println("Hack"); } } public static void main(String[] args) { ClickIt clickit = new ClickIt(); clickit.doIt(); } } package click; public class CodeTalk { public void doIt() { printMessage(); } void printMessage() { System.out.println("Click"); } }
Solution 70: Package Deal
This puzzle appears straightforward. The
main method in hack.TypeIt instantiates the class
TypeIt.ClickIt and invokes its doIt method, which is inherited
from CodeTalk. This method, in turn, calls printMessage, which
is declared in TypeIt.ClickIt to print Hack. And yet, if you
run the program, it prints Click. How can this be?
This analysis incorrectly assumes that
hack.TypeIt.ClickIt.printMessage overrides
click.CodeTalk.printMessage. A
package-private method cannot be directly overridden by a method in a different
package [JLS 8.4.8.1]. The two printMessage methods in this
program are unrelated; they merely have the same name. When the program calls
printMessage from within the package hack, the package-private
method hack.TypeIt.ClickIt.printMessage is run. This method prints
Click, which explains the observed behavior.
If you want the printMessage method in
hack.TypeIt.ClickIt to override the method in click.CodeTalk,
you must add the protected or public modifier to the method
declaration in click.CodeTalk. To make the program compile, you must
also add a modifier to the overriding declaration in
hack.TypeIt.ClickIt. This modifier must be no more restrictive than the
one you placed on the declaration for printMessage in
hack.TypeIt.ClickIt [JLS 8.4.8.3]. In other words, both
printMessage methods may be declared public, both may be
declared protected, or the superclass method may be declared protected
and the subclass method public. If any of these three changes is made,
the program will print Hack, indicating that overriding is taking
place.
In summary, package-private methods cannot be directly
overridden outside the package in which they're declared. Although the
combination of package-private access and overriding can lead to some confusion,
Java's current behavior enables packages to support encapsulation of
abstractions larger than a single class. Package-private methods are
implementation details of their package, and reuse of their names outside the
package should have no effect inside the package.
No comments:
Post a Comment
Your comments are welcome!