2

我正在查看一些 java 代码,其中类的构造函数如下所示:

public class X extends ... {
    X(String s) {
       super(new Y(s)); 
    }
}

那总是错的吗?换句话说,它是否在构造函数中创建一个对象以将其传递给“超级”总是错误的?如果是,为什么?

编辑:为什么我认为这可能是错误的?

当创建一个类 X 时,jvm 做的第一件事就是在它的超类上调用 super。(即使暗示了 'super()' 也会这样做)您只能执行有限数量的操作,例如super(new Y(s)); 使用三元运算符调用 supersuper( s != null ? new Y(s) : new Y() ) 但您将无法放置更多逻辑,因为必须首先调用 super !!!这就是为什么我认为这是错误的

4

5 回答 5

3

不,这并不总是错误的。子类锁定超类允许您在构造函数中指定的内容是完全有效的。


重新编辑:

...但是您将无法提出更多逻辑,因为调用super...

没错,这是 Java 编程语言的一个限制(我怀疑是有意的限制),但这并不意味着创建一个传递给super.

如果您愿意,您可以通过定义一个返回您需要传递的内容super并调用它的静态函数来绕过该限制:

super(makeTheThingYouNeed());

那时我肯定会在使用它之前仔细检查这确实是我最好的做法。但只是专门创建一个对象将其传递给super? 根本不是问题。

于 2013-03-05T17:12:14.883 回答
0

这并不总是错误的,但像往常一样,应该采取措施防止滥用。

在这种情况下,新对象似乎是StringY的包装器,或者它是. 您只是提供超类的初始化值,并在需要时调整它们。sX

Y对象可以在X的构造函数中创建或直接作为参数提供(使用X的构造函数接收 anY而不是 a String)。例如,Y如果它是您无权从创建的对象访问的类,则创建X.

正如您所看到的,这完全取决于您正在编码的当前上下文。正是这个上下文决定了一个决策的错误程度。

于 2013-03-05T17:14:06.913 回答
0

这不是“总是”错的。它甚至不是“大部分”错误或失礼。就此而言,子类以super这种方式传递信息是相当普遍的。但是人们确实想知道其他情况可能是什么,其中大多数与实践本身无关。

这是一种绕过更广泛的类初始化的方法吗?那么也许这是一个坏主意。是否使阅读/调试代码变得更加困难?那么也许它应该被排除在外。

我也想知道谁告诉你这总是错的,为什么他们这么说。是开发人员吗?同学?导师?明确地说“构造函数内部的初始化是错误的”不是我见过的,但我可以想象一个认为他知道但不知道的学生或教授会说什么。

于 2013-03-05T17:14:47.237 回答
0

不,这并不总是错误的,例如

public class A {
  public A(final BigDecimal value) {}
}

public class B extends A {
  public B(final String value) {super(new BigDecimal(value));}
}

这样做可能有很多原因,变量的转换(如上所述)或者超类可能采用某个protected只能实例化的类的B实例。

很少有事情总是错的,但很多事情有时是错的......

于 2013-03-05T17:14:58.663 回答
0

在任何语言意义上都没有错。但是,也许它“闻起来”(正如您在评论中所说的那样),因为如果构造函数采用完全不同类型的参数,则子类关系X与其超类之间的关系似乎不一致。

这是一个主观问题,更多地与 OO 设计理念有关,而不是与编码实践有关。作为代码,子类限制可以用来创建对象的数据类型是完全合理的。事实上,这样做很常见。

于 2013-03-05T17:18:36.693 回答