Reputation: 137
I need a method in a class that is going to be used in subclasses, although this method uses a property that is changed in subclasses. Is there a way to access the property of the subclass without having to override the method?
I've tried using a getter for the property, but got the same result.
public class SuperClass {
private static final String a = "Super";
public void superMethod(){
System.out.println("SuperMethod: " + a);
}
}
public class ChildClass extends SuperClass {
private static final String a = "Child";
}
public class Main {
public static void main(String[] args) {
SuperClass s = new SuperClass();
ChildClass c = new ChildClass();
s.superMethod();
c.superMethod();
}
}
The console shows:
SuperMethod: Super
SuperMethod: Super
The expected result is:
SuperMethod: Super
SuperMethod: Child
Upvotes: 0
Views: 595
Reputation: 8705
It isn't clear exactly what you are doing, but your String a
members are private static
members of the class, not of the individual objects.
If you made String a
a member of the object, instead of the class, you could override the value during the creation of the child class:
U:\>jshell
| Welcome to JShell -- Version 12
| For an introduction type: /help intro
jshell> class SuperClass {
...> protected final String a;
...>
...> protected SuperClass(String _a) {
...> a = _a;
...> }
...>
...> public SuperClass() {
...> this("Super");
...> }
...>
...> public void superMethod() {
...> System.out.println("SuperMethod: "+a);
...> }
...> }
| created class SuperClass
jshell> class ChildClass extends SuperClass {
...> public ChildClass() {
...> super("Child");
...> }
...> }
| created class ChildClass
jshell> var s = new SuperClass();
s ==> SuperClass@4566e5bd
jshell> var c = new ChildClass();
c ==> ChildClass@ff5b51f
jshell> s.superMethod();
SuperMethod: Super
jshell> c.superMethod();
SuperMethod: Child
Update
Now that we know your actual use-case (from a comment, below), what you want to implement is pretty simple:
class SuperClass {
private final static Logger LOG = Logger.getLogger(SuperClass.class);
protected Logger getLogger() { return LOG; }
public void superMethod(){
getLogger().info("superMethod() called.");
}
}
class ChildClass extends SuperClass {
private final static Logger LOG = Logger.getLogger(ChildClass.class);
@Override
protected Logger getLogger() { return LOG; }
}
public class Main {
public static void main(String[] args) {
SuperClass s = new SuperClass();
ChildClass c = new ChildClass();
s.superMethod(); // Message logged to SuperClass.LOG
c.superMethod(); // Message logged to ChildClass.LOG
}
}
Upvotes: 1
Reputation: 72379
I've tried using a getter for the property, but got the same result.
Are you sure? The following should be exactly what you're after:
class SuperClass {
private String a = "Super";
public void superMethod() {
System.out.println("SuperMethod: " + getA());
}
public String getA() {
return this.a;
}
}
class ChildClass extends SuperClass {
private String a = "Child";
@Override
public String getA() {
return this.a;
}
}
public class Main {
public static void main(String[] args) {
SuperClass s = new SuperClass();
ChildClass c = new ChildClass();
s.superMethod();
c.superMethod();
}
}
Note that the getters can't be private (otherwise they can't be accessed from outside the class), and they can't be static (otherwise they're part of the class, not any instances of that class.)
Upvotes: 5
Reputation: 1030
Short answer: Java cannot do it the way you want since the compiler will merge String literal with final values, so "SuperMethod: " + a
will get translated to "SuperMethod: Super"
in the resulting bytecode.
The only solution is using reflection (if you must):
import java.lang.reflect.Field;
public class Main {
public static void main(String[] args) {
SuperClass s = new SuperClass();
ChildClass c = new ChildClass();
s.superMethod();
c.superMethod();
}
}
class SuperClass {
private static final String a = "Super";
public void superMethod(){
try{
final Class<?> clazz = this.getClass();
final Field fieldA = clazz.getDeclaredField("a");
fieldA.setAccessible(true);
final String value = (String)fieldA.get(null);
System.out.println("SuperMethod: " + value);
} catch (final NoSuchFieldException | IllegalAccessException ex){
// Because reflection
ex.printStackTrace();
}
}
}
class ChildClass extends SuperClass {
private static final String a = "Child";
}
Output is:
SuperMethod: Super
SuperMethod: Child
But, honestly, I would still favor using classic override:
public class Main {
public static void main(String[] args) {
SuperClass s = new SuperClass();
ChildClass c = new ChildClass();
s.superMethod();
c.superMethod();
}
}
class SuperClass {
private static final String a = "Super";
public void superMethod(){
System.out.println("SuperMethod: " + getA());
}
public String getA() {
return a;
}
}
class ChildClass extends SuperClass {
private static final String a = "Child";
@Override
public String getA() {
return a;
}
}
Upvotes: 0