开发者

Why would you have two constructors with the same signature?

开发者 https://www.devze.com 2022-12-31 11:34 出处:网络
What are the use cases of having two constructors with the same signature? Edit: You cannot do that in Java because of which Effective Java says you need static factor开发者_运维百科y. But I was won

What are the use cases of having two constructors with the same signature?

Edit: You cannot do that in Java because of which Effective Java says you need static factor开发者_运维百科y. But I was wondering why would you need to do that in the first place.


The reason you'd think you wanted to do this is that you've found yourself in a situation where variable type isn't sufficient context.

For example, I might fool myself into thinking that I need to give my Point class two constructors: one which works by X and Y, and one by degrees and radians. Both might be represented as float.

So I'd think I needed two constructors with identical signatures (float, float).

Dr. Bloch points out that it's better to make factory methods:


    public static Point newPointByDegreesAndRadians (float degrees, float radians);
    public static Point newPointByXandY (float x, float y);

Incidentally, another alternative to factory methods is to create types which carry the context which is missing from the datatypes, like this:


    public class CoordinatesXY {
       float X;
       float Y;
       ...
    }
    public class CoordinatesDegreesRadians {
       float degrees;
       float radians;
       ...
    }
    public Point (CoordinatesXY coordinates) { ... }
    public Point (CoordinatesDegreesRadians coordinates) { ... }

Whether you think this is clearer than the factory methods is a matter of taste. For this specific case, my own feeling is that the two coordinates classes are only of use if your design makes coordinates useful on their own, separate from a point at those coordinates.


The reason you would want to have two (or more) constructors with the same signature is that data type is not synonymous with meaning.

A simple example would be a Line class.

Here's one constructor: public class Line(double x1, double y1, double x2, double y2)

Here's another: public class Line(double x1, double y1, double angle, double distance)

The first constructor defines two end points of a line. The second constructor defines one end point, and the angle and distance to the second end point.

Java cannot distinguish between the two Line class constructors, true. But there are good reasons for 2 or more constructors to have the same signature.


A Class cannot have two constructors with the same signature.

From the JLS:

8.8.2 Constructor Signature

It is a compile-time error to declare two constructors with override-equivalent (§8.4.2) signatures in a class. It is a compile-time error to declare two constructors whose signature has the same erasure (§4.6) in a class.


To answer your new edited question, the intent would be if you had a class which could have two logically different actions but that happen to be the same signature.

For example, say you had a Person class that cared about someone's name and place of birth.

public Person(String name) { ... }
public Person(String placeOfBirth) { ... }

Obviously, this doesn't work.

You have to use a factory:

public static Person personWithName(String name) { ... }
public static Person personFromPlace(String placeOfBirth) { ... }

Obviously a contrived example, but that's the general idea...


You wouldn't, and you can't anyway. It wouldn't compile the class files into bytecode as there's no way for the program to differentiate between them to decide which one to use.


@kunjaan - there are very few use cases for such an idea even if there was a technically valid way to do it (which in Java there isn't - see other answers).

One possible use case would be different constructor implementations based on some external condition - for example, a constructor which could allocate certain memory if it was not available, or re-use that memory from some common pool in the program if it became available.

Another example of that would be a constructor which would implement certain things using a more efficient system call if the current architecture supported that system call. BTW, both of these example are a bit harder to imagine in Java but easier to imagine in C++ -land, but you get the overall idea hopefully.

In either case, this would be actually coded by either having a factory as you mentioned, OR having a single constructor, which implements some sort of environment-based decision and calls a helper method with different signatures to actually perform needed initialization that is implementation dependent, e.g. (in pseudocode, language independent)

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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号