简体   繁体   English

Java在子类构造函数中初始化基类字段

[英]java initialize base class fields in subclass constructor

This is a very basic question about subclasses in java, I still don't get it... 这是关于Java子类的一个非常基本的问题,我还是不明白。

Suppose I have a superclass with three fields and with only the default constructor: 假设我有一个具有三个字段且仅具有默认构造函数的超类:

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

and I want to add a field x. 我想添加一个字段x。 I cannot change Superclass , so I make a subclass: 我不能更改Superclass ,所以我创建了一个子类:

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

I now want to generate a Subclass object from an existing Superclass object: 我现在想从现有的Superclass对象生成一个Subclass Superclass对象:

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

such that I can still access sc.a , sc.b etc. 这样我仍然可以访问sc.asc.b

How can I best do this without assigning all these fields 'by hand' in the constructor of the subclass? 如何最好地做到这一点,而无需在子类的构造函数中“手动”分配所有这些字段?

You have to assign a value to the variables either in the base-class constructor or in the child class. 您必须在基类构造函数或子类中为变量分配一个值。

You can declare a parameterized constructor in sub-class to assign the value to a variable in the superclass 您可以在子类中声明参数化的构造函数,以将值分配给超类中的变量

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

Or you can declare a parameterized constructor in BaseClass, and in child class, instead of calling super() , call that parametrized constructor super(a,b,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;
 }
}

Other than copying by hand you can't. 除了手动复制外,您不能这样做。

Java is not JavaScript where objects are prototypes of other objects, instead in Java, classes subclass other classes. Java不是JavaScript,其中对象是其他对象的原型,而在Java中,类将其他类子类化。

I now want to generate a Subclass object from an existing Superclass object 我现在想从现有的超类对象生成一个子类对象

In fact no, you will instantiate a Subclass object by relying on the state of a Superclass object. 实际上,不,您将依赖于Superclass对象的状态来实例化Subclass对象。

As you pass the SuperClass as parameter of the Subclass constructor, you just need to use fields of it to invoke the super constructor if you declare it : 当您将SuperClass作为Subclass构造函数的参数传递时,如果您声明了它,则只需使用它的字段来调用超级构造函数:

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

Or if you have a super constructor with no arg : 或者,如果您有一个没有arg的超级构造函数:

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

Note that in Java using the private modifier for instance fields is strongly encouraged and you should access to field via public methods. 请注意,在Java中,强烈建议将private修饰符用于实例字段,并且您应该通过public方法访问字段。

A cleaner way for your constructor would look like : 为您的构造函数提供的更简洁的方法如下所示:

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
}

If you truly cannot change the superclass, then the only way you can inspect and modify the values of the member variables is by using reflection . 如果您确实无法更改超类,则可以检查和修改成员变量的值的唯一方法是使用reflect

You should note that if getters and setters aren't exposed to subclasses (ie they are private ) then there's a question of whether the original creator of class wanted you to ever have access to the contained variables in the first place. 您应该注意,如果getter和setter不暴露于子类(即它们是private ),则存在一个问题,即类的原始创建者是否希望您曾经有权访问所包含的变量。 Would your assignments change the behaviour of the parent in an unpredictable/unsupported way? 您的作业会以一种无法预测/无法支持的方式改变父母的行为吗?

If the SuperClass is of your own design, then you should ensure that you always use getters and setters so that you may define the proper protocol (way to interact) with your class unambiguously. 如果SuperClass是您自己设计的,则应确保始终使用getter和setter,以便可以与类明确定义正确的协议(交互方式)。 This rule also applies for the visibility of class constructors. 此规则也适用于类构造函数的可见性。 Generally speaking, every member variable of a class should be possible to initialize via a class constructor; 一般而言,类的每个成员变量都应该可以通过类构造函数进行初始化。 whether that constructor is visible, or exposes all of the possible parameters to subclasses or upon allocation by external sources, is a different story. 无论该构造函数是否可见,还是将所有可能的参数公开给子类还是由外部资源分配,都是另一回事。

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

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