繁体   English   中英

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

[英]Is there a way to access a subclass element from a super class?

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

我已经尝试过使用该属性的吸气剂,但得到相同的结果。

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

控制台显示:

超级方法:超级

超级方法:超级

预期结果是:

超级方法:超级

超级方法:子级

我已经尝试过使用该属性的吸气剂,但得到相同的结果。

你确定吗? 以下就是您所追求的:

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不能是私有的(否则它们不能从类外部访问),并且不能是静态的(否则它们是该类的一部分,而不是该类的任何实例)。

目前尚不清楚您在做什么,但是您的String a成员是该类的private static成员,而不是单个对象的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
    }
}

简短的答案: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;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM