有没有办法从超类访问子类元素?

时间:2019-07-11 22:09:33

标签: java

我需要一个将在子类中使用的类中的方法,尽管该方法使用的属性在子类中已更改。有没有一种方法可以访问子类的属性而不必重写该方法?

我已经尝试过使用该属性的getter方法,但是得到了相同的结果。

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();
    }
}

控制台显示:

SuperMethod:超级

SuperMethod:超级

预期结果是:

SuperMethod:超级

SuperMethod:孩子

3 个答案:

答案 0 :(得分:5)

  

我已经尝试过使用该属性的getter方法,但是得到了相同的结果。

确定吗?以下应该正是您所追求的:

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();
    }
}

请注意,getter不能是私有的(否则它们不能从类外部访问),并且不能是静态的(否则它们是类的一部分,而不是该类的任何实例)。 )

答案 1 :(得分:1)

不清楚您在做什么,但是您的String a成员是该类的private static成员,而不是单个对象的成员。

如果使String a成为对象的成员而不是类的成员,则可以在创建子类的过程中覆盖该值:

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

更新

现在我们知道了您的实际用例(从下面的评论中),您想要实现的内容非常简单:

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
    }
}

答案 2 :(得分:0)

简短的答案:Java无法按照您想要的方式进行操作,因为编译器会将String常量与最终值合并,因此"SuperMethod: " + a将在生成的字节码中转换为"SuperMethod: Super"

唯一的解决方案是使用反射(如果需要):

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";
}

输出为:

SuperMethod: Super
SuperMethod: Child

但是,老实说,我还是会喜欢使用经典替代:

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;
    }
}