【问题标题】:java initialize base class fields in subclass constructorjava在子类构造函数中初始化基类字段
【发布时间】:2019-01-21 12:46:10
【问题描述】:

这是一个关于java中子类的非常基本的问题,我还是不明白...

假设我有一个包含三个字段且只有默认构造函数的超类:

public class Superclass {
    public int a;
    public int b;
    public int c;
}

我想添加一个字段 x。我无法更改Superclass,所以我创建了一个子类:

public class Subclass extends Superclass {
    public int x;
    public Subclass(Superclass s) {
        super();
        // what to do??
    }
}

我现在想从现有的Superclass 对象生成Subclass 对象:

Superclass s = new Superclass();
s.a = "a";
s.b = "b";
Subclass sc = new Subclass(s);
sc.x = "x";

这样我仍然可以访问sc.asc.b 等。

如果不在子类的构造函数中“手动”分配所有这些字段,我如何才能最好地做到这一点?

【问题讨论】:

标签: java oop constructor subclass superclass


【解决方案1】:

您必须在基类构造函数或子类中为变量赋值。

您可以在子类中声明一个参数化构造函数,以将值分配给超类中的变量

class Subclass extends Superclass {
public int x;
public Subclass(int a,int b, int c,int x) {
    super();
    this.x = x;
    this.a=a;
    this.b=b;
    this.c=c;
 }
}

或者您可以在 BaseClass 和子类中声明一个参数化构造函数,而不是调用 super(),而是调用该参数化构造函数super(a,b,c)

class Superclass {
public int a;
public int b;
public int c;

public Superclass(int a, int b, int c) {
    this.a = a;
    this.b = b;
    this.c = c;
 }   
}

class Subclass extends Superclass {
public int x;

public Subclass(int a,int b, int c,int x) {
    super(a,b,c);
    this.x = x;
 }
}

【讨论】:

  • 是的,我知道,但是我的超类中有很多字段,我想避免将它们全部写在子类构造函数中...
  • @user1981275 请参阅 Ashish 发布的第二个示例。
【解决方案2】:

如果您确实无法更改超类,那么检查和修改成员变量值的唯一方法是使用reflection

您应该注意,如果 getter 和 setter 没有暴露给子类(即它们是 private),那么问题是类的原始创建者是否希望您能够访问包含的变量.您的分配是否会以不可预测/不受支持的方式改变父母的行为?

如果SuperClass 是您自己设计的,那么您应该确保始终使用getter 和setter,以便您可以明确地定义与您的类的正确协议(交互方式)。此规则也适用于类构造函数的可见性。一般来说,类的每个成员变量都应该可以通过类构造函数进行初始化;该构造函数是可见的,还是将所有可能的参数公开给子类或由外部资源分配时,是另一回事。

【讨论】:

    【解决方案3】:

    我现在想从现有的超类生成一个子类对象 对象

    实际上不,您将依赖Superclass 对象的状态来实例化Subclass 对象。

    当您将SuperClass 作为Subclass 构造函数的参数传递时,如果您声明它,您只需要使用它的字段来调用超级构造函数:

    public Subclass(Superclass s) {
        super(s.a, s.b, s.c); // constructor  may simplify
    }
    

    或者如果你有一个没有 arg 的超级构造函数:

    public Subclass(Superclass s) { 
        a = s.a;
        b = s.b;
        c = s.c;
    }
    

    请注意,在 Java 中,强烈建议对实例字段使用 private 修饰符,并且您应该通过 public 方法访问字段。

    构造函数的一种更简洁的方式如下所示:

    public SuperClass(int a, int b, int c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }
    
    public Subclass(Superclass s) {
        super(s.getA(), s.getB(), s.getC()); // constructor  may simplify
    }
    

    【讨论】:

      【解决方案4】:

      除了手抄,你不能。

      Java 不是 JavaScript,其中对象是其他对象的原型,而是在 Java 中,类是其他类的子类。

      【讨论】:

        猜你喜欢
        • 2015-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-24
        • 2023-03-31
        • 2014-07-02
        相关资源
        最近更新 更多