有两个具有相同签名的构造函数有什么用例?
编辑:你不能用Java做到这一点,因为Effective Java说你需要静态工厂。但我想知道为什么你首先需要这样做。
答案 0 :(得分:15)
你想想要这样做的原因是你发现自己处于变量类型不足的情况。
例如,我可能会欺骗自己以为我需要给我的Point类提供两个构造函数:一个用X和Y工作,一个用度和弧度工作。两者都可以表示为浮动。
所以我认为我需要两个具有相同签名的构造函数(float,float)。
博士。 Bloch指出制作工厂方法更好:
public static Point newPointByDegreesAndRadians (float degrees, float radians);
public static Point newPointByXandY (float x, float y);
顺便提一下,工厂方法的另一种替代方法是创建带有数据类型中缺少的上下文的类型,如下所示:
public class CoordinatesXY {
float X;
float Y;
...
}
public class CoordinatesDegreesRadians {
float degrees;
float radians;
...
}
public Point (CoordinatesXY coordinates) { ... }
public Point (CoordinatesDegreesRadians coordinates) { ... }
您是否认为这比工厂方法更清晰是一个品味问题。对于这种特殊情况,我自己的感觉是,如果你的设计使坐标有用,与这些坐标上的点分开,那么两个坐标类才有用。
答案 1 :(得分:11)
您希望拥有两个(或更多)具有相同签名的构造函数的原因是数据类型与含义不同义。
一个简单的例子是Line类。
这是一个构造函数:public class Line(double x1, double y1, double x2, double y2)
这是另一个:public class Line(double x1, double y1, double angle, double distance)
第一个构造函数定义一条线的两个端点。第二个构造函数定义了一个端点,以及到第二个端点的角度和距离。
Java无法区分两个Line类构造函数,true。但是有两个或更多构造函数具有相同签名的充分理由。
答案 2 :(得分:5)
一个Class不能有两个具有相同签名的构造函数。
8.8.2构造函数签名
在类中声明具有覆盖等效(§8.4.2)签名的两个构造函数是编译时错误。声明两个构造函数的编译时错误,其签名在类中具有相同的擦除(第4.6节)。
答案 3 :(得分:3)
要回答您新编辑的问题,目的是如果您有一个类可能有两个逻辑上不同的操作,但恰好是相同的签名。
例如,假设您有一个关心某人姓名和出生地的人员课程。
public Person(String name) { ... }
public Person(String placeOfBirth) { ... }
显然,这不起作用。
你必须使用工厂:
public static Person personWithName(String name) { ... }
public static Person personFromPlace(String placeOfBirth) { ... }
显然是一个人为的例子,但这是一般的想法......
答案 4 :(得分:2)
你不会,反正你也不能。它不会将类文件编译成字节码,因为程序无法区分它们以决定使用哪一个。
答案 5 :(得分:1)
@kunjaan - 即使有一种技术上有效的方法(在Java中没有 - 看其他答案),这种想法的用例很少。
一个可能的用例是基于某些外部条件的不同构造函数实现 - 例如,如果某个内存不可用则可以分配某些内存的构造函数,或者如果它变为可以从程序中的某个公共池重新使用该内存可用。
另一个例子是构造函数,如果当前架构支持该系统调用,它将使用更有效的系统调用来实现某些事情。顺便说一下,这两个例子在Java中都有点难以想象,但在C ++ -land中更容易想象,但是你有希望得到整体想法。
在任何一种情况下,这实际上都可以通过如你所提到的工厂或具有单个构造函数来编码,该构造函数实现某种基于环境的决策并调用具有不同签名的辅助方法来实际执行所需的初始化是依赖于实现的,例如(伪代码,语言无关)
function helper_initializer(signature for case 1) {
}
function helper_initializer(signature for case 2) {
}
function constructor() {
// constructor logic here
if (environmental_consdition() == 1) {
this->helper_initializer(signature for case 1);
} else {
this->helper_initializer(signature for case 2);
}
}