I have a problem with name hiding that is extremely hard to solve. Here is a simplified version that explains the problem:
There is a class: org.A
package org; public class A{ public class X{...} ... protected int net; }
Then there is a class net.foo.X
package net.foo; public class X{ public static void doSomething(); }
And now, here is the problematic class which inherits from A
and wants to call net.foo.X.doSomething()
package com.bar; class B extends A { public void doSomething(){ net.foo.X.doSomething(); // doesn't work; package net is hidden by inherited field X.doSomething(); // doesn't work; type net.foo.X is hidden by inherited X } }
As you see, this is not possible. I cannot use the simple name X
because it is hidden by an inherited type. I cannot use the fully qualified name net.foo.X
, because net
is hidden by an inherited field.
Only the class B
is in my code base; the classes net.foo.X
and org.A
are library classes, so I cannot alter them!
My only solution looks like this: I could call another class that in turn calls X.doSomething()
; but this class would only exist because of the name clash, which seems very messy! Is there no solution in which I can directly call X.doSomething()
from B.doSomething()
?
In a language that allows specifying the global namespace, e.g., global::
in C# or ::
in C++, I could simply prefix net
with this global prefix, but Java does not allow that.
A field or variable with the same name in subclass and superclass is known as variable hiding or field hiding in Java. When a variable is hidden, you can use super. variableName to access the value from a superclass.
Within a class, a field that has the same name as a field in the superclass hides the superclass's field, even if their types are different. Within the subclass, the field in the superclass cannot be referenced by its simple name.
You can cast a null
to the type and then invoke the method on that (which will work, since the target object isn't involved in invocation of static methods).
((net.foo.X) null).doSomething();
This has the benefits of
net.foo.X
),B
the name you want it to have; that's why a import static
won't work in your exact case),The downside is that this code is really horrible! For me, it generates a warning, and that's a good thing in general. But since it's working around a problem that is otherwise thoroughly impractical, adding a
@SuppressWarnings("static-access")
at an appropriate (minimal!) enclosing point will shut the compiler up.
Probably the simplest (not necessarily the easiest) way to manage this would be with a delegate class:
import net.foo.X; class C { static void doSomething() { X.doSomething(); } }
and then ...
class B extends A { void doX(){ C.doSomething(); } }
This is somewhat verbose, but very flexible - you can get it to behave any way you want; plus it works in much the same way both with static
methods and instantiated objects
More about delegate objects here: http://en.wikipedia.org/wiki/Delegation_pattern
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With