【问题标题】:Passing superclass object as parameter to subclass constructor (java)将超类对象作为参数传递给子类构造函数(java)
【发布时间】:2016-04-21 10:13:22
【问题描述】:

我已经进行了一些搜索,但我要么没有问正确的问题,要么没有正确记住。无论如何,在 Java 中,我想知道是否可以将超类对象作为参数传递给子类,以及使该对象的数据可用于类的超类的最有效方法是什么。

代码示例:

public class superclass {
  String myparm1;
  String myParm2;
  int myParmN;

  public superclass(String p1, String p2, int pn)
  {
    this.myparm1 = p1;
    this.myparm2 = p2;
    this.myParmN = pn;
  }
  // other methods here
}

public class subclass extends superclass {
  double b1;
  double b2;

  public subclass(superclass sc, double b1, double b2) {
    // easy way to make sc data available to this class?
    // Do I create a copy or clone method, or some other way?
    // calling super(sc); wouldn't exactly work 
    this.b1 = b1;
    this.b2 = b2;
  }
}

如果我在超类中有一个构造函数 public superclass(superclass sc) { // assign sc properties to this properties, correct? },那么我可以简单地使用 super(sc);

【问题讨论】:

  • 如果超类构造函数需要两个字符串和一个 int,则必须使用 2 个字符串和一个 int 调用 super()。没有办法解决它。如果sc暴露了这3个值,则获取它们,并将它们apsss到super()。
  • 你为什么不super(sc.p1, sc.p2, sc.p3)
  • superclass(superclass sc)?那时调用super(sc) 甚至都行不通,因为没有Object 构造函数以superclass 作为参数
  • 拉斐尔。当然,对于少量的属性,这很容易。但是假设我的班级有大量的属性。 (当然,在那种情况下,这可能是糟糕的设计,但我离题了。)
  • @Macchtyn - 如果你的超类有大量的属性,封装复制它的细节就变得更重要了。您能否在superclass 类中添加一个复制构造函数,格式为您在问题末尾注明的形式——public superclass(superclass sc)

标签: java inheritance


【解决方案1】:

在构造函数中传递对对象超类的引用是没有意义的。您的子类已经是超类的一个实例。

即使您不能直接看到超类的私有组件,但它们仍然存在,并且对公共访问器方法的调用仍然会产生正常行为。

在回答您的第二个问题时,访问父类内部数据的最有效方法是使用该父类的访问器方法。如果它具有填充一些充满属性的数据结构的 get/set 属性方法,只需从您的子类中调用这些方法,它们的工作方式与它们对父类的工作方式完全相同。现在,如果这些内部数据结构由父类的构造函数填充,那么当您创建需要它们的子构造函数的实例时,您必须使用正确的方法调用该构造函数 - 通常通过调用适当的 super()在孩子的构造函数的开头。

如果您试图绕过不能看到超类的私有部分的限制,Java 故意不允许您这样做。除非您被困在不允许这样做的执行环境中,否则您可以通过反射解决此问题,但我通常不认为这是一种安全或优雅的方法。

从下面的评论中,我了解 OP 正在尝试做什么,这应该可行,但显然这取决于您对超类进行更改的能力:

public class Super
{
    public Super (Super other)
    {
        //copy stuff from other to this
    }
}

public class Child extends Super
{
    public Child (Super other)
    {
        super(other);
        //continue constructor
    }

}

【讨论】:

  • 来自 OP 的文本,特别强调:“传递超类 object”。
  • 因此,您正在尝试找出一种方法来获取已经实例化的超类实例,将其传递给子类的构造函数,并使用该父实例作为初始化的一部分放在孩子的构造函数中?
  • 正确,吉姆。已经实例化的实例。而且,我同意你最后的说法。如果我的超类具有未公开的私有数据(并且需要保持这种状态),那么复制构造函数尝试将这些数据反映出来将是糟糕的设计。
  • 除非超类被编写为显式地允许这种情况发生(即构造函数,它采用同一类的另一个实例并复制部分),它不是 java 自然支持的东西。您可以使用 public Super (Super super) (//将字段从 super 复制到 this) 来完成此操作,然后在子类中您将拥有类似 public Child (Super super) {super(super); ....}
【解决方案2】:

你不能。当您使用 Java 构建对象时(例如使用 new),该实例有一个类,并且该类有一个父类(可能是 Object)。

父子关系只存在于类之间,而不是对象之间!没有对象有父对象(至少在语言级别上没有) - 所以你不能接受构造函数中的父对象并将其存储在 Java 定义的某个地方。

但是,您的域可以有父实体和子实体,在这种情况下,您需要字段或数据结构来存储它们之间的链接。

【讨论】:

  • 听起来 OP 有一个 superclass 对象,并想用它来初始化一个新的 subclass 对象的超类部分。给定一个合适的超类构造函数,这是可行的。
  • 但是他可以简单地使用super(arg.p1, arg.p2, ...) - 我已经在我对原始问题的评论中提出了这个问题
【解决方案3】:

要回答上一个问题,假设超类具有大量属性。在这种情况下,当然,类的设计可能很糟糕。

也许最好的答案是:

public class superclass {
  // properties and constructors as defined in OP

  public void copy(superclass sc) {
    this.myParm1 = sc.getMyParm1();
    this.myParm2 = sc.getMyParm2();
    this.myParmN = sc.getMyParmN();
  }

  // other methods as needed
}

这样子类就可以直接调用super.copy(sc)。当然,我需要超类中的另一个构造函数来设置默认值:public superclass() { // set defaults }

所以子类可以是:

public class subclass extends superclass {
  //properties as defined in OP

  public subclass(superclass sc, double b1, double b2) {
    this.b1 = b1;
    this.b2 = b2;
    super.copy(sc);
  }
}

这样,我只需输入这些参数,任何想要接受超类对象的子类都不必每次都定义该结构。 (更少的打字,更少的出错或忘记的机会。)

【讨论】:

  • 如果您想复制到现有对象中,copy() 方法会有所帮助。但是你的例子是关于建筑的。对于施工,最好提供构造函数。 (如果实例是不可变的,这是必要的。)如果您想同时支持复制构造和复制分配,您可以同时提供构造函数和方法,并可选择在它们之间共享一个实现。
  • 安迪,感谢您为我指明了正确的方向并最终提出了正确的问题。复制构造函数:javapractices.com/topic/TopicAction.do?Id=12
猜你喜欢
  • 2015-04-26
  • 1970-01-01
  • 1970-01-01
  • 2012-10-30
  • 1970-01-01
  • 1970-01-01
  • 2014-06-04
  • 2013-12-12
  • 2019-09-29
相关资源
最近更新 更多