简体   繁体   English

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

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

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 超级方法:子级

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

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

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: 如果使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

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

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

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

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

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