...
Code Block |
---|
|
class MyVector {
private int val = 1;
private void doLogic() {
int newValue;
//...
}
}
|
Noncompliant Code Example (Method Shadowing)
Method shadowing in different scopes becomes possible when two or more packages are used. Method shadowing differs from method overloading in that subclasses are allowed to inherit overloadings defined in the base class. It differs from hiding because the methods do not need to be declared static
. It is also distinct from method overriding, as exemplified in this noncompliant code example.
Code Block |
---|
|
package x;
public class A {
void doLogic() { // default accessibility
// print 'A'
}
public static void main(String[] args) {
A a = new y.C();
a.doLogic(); // invokes doLogic() of class x.B and prints 'B'
}
}
|
Code Block |
---|
|
package x;
public class B extends A {
void doLogic() { // default accessibility
// print 'B'
}
}
|
Code Block |
---|
|
package y; // different package
public class C extends x.B { // public accessibility
public void doLogic() {
// print 'C'
}
}
|
Note that class y.C
is accessible from the package x
and so is its doLogic()
method. However, if the main()
method, defined in class A
, tries to polymorphically invoke y.doLogic()
as shown, the override corresponding to class B in package x
takes precedence. This is because the doLogic()
methods in classes x.A
and x.B
are not visible from class y.C
due to the default
access specifier. As a result, the class x.C
is not considered a part of the overriding hierarchy. Note, however, that the code behaves as expected if the access specifiers of all of the methods are changed to public
.
Compliant Solution (Method Shadowing)
Use a different name to indicate that the class residing in another package is not intended to be part of the overriding chain. A programmer can use dotted notation to explicitly specify which class defines the method to be invoked. Avoid reusing names even when all the relevant classes define the affected methods with a public
access specifier; future evolution of one or more of the classes can reduce method accessibility, leading to unexpected results.
Code Block |
---|
|
package x;
public class A {
void doLogic() {
// print 'A'
}
public static void main(String[] args) {
// explicitly invokes doSequence() of class y.C and prints 'C'
y.C.doSequence();
}
}
|
Code Block |
---|
|
package x;
public class B { /* ... */ }
|
Code Block |
---|
|
package y; // different package
public class C extends x.B {
public void doSequence() { // now renamed
// print 'C'
}
}
|
Exceptions
SCP02-EX1: Reuse of names is permitted for trivial loop counter declarations in the same scope:
...