Two constructors that do different things, but use the same data type
I recently ran into this problem with my class MorseString
. I have two different constructors that do different things but take the same data type:
/*
* Constructor that takes the Morse Code as a String as a parameter
*/
public MorseString(String s) {
if(!isValidMorse(s)) {
throw new IllegalArgumentException("s is not a valid Morse Code");
}
// ...
}
and
/*
* Constructor that takes the String as a parameter and converts it to Morse Code
*/
public MorseString(String s) {
// ...
}
I came up with this solution:
public MorseString(String s, ParameterType type) {
if(type == ParameterType.CODE) {
if(!isValidMorse(s)) {
throw new IllegalArgumentException("s is not a valid Morse Code");
}
// Constructor that takes Morse
} else {
// Constructor that takes String
}
}
But it looks ugly. Any other solutions?
source to share
Since one of the constructors expects Morse code data to be ready (so it's more like a "constructor" - literally constructs an object from the data) and the other needs to do some conversion, it might make more sense to create a static factory method called convert
:
/*
* Constructor that takes the Morse Code as a String as a parameter
*/
public MorseString(String s) {
if(!isValidMorse(s)) {
throw new IllegalArgumentException("s is not a valid Morse Code");
}
// ...
}
/*
* Factory method that takes the String as a parameter and converts it to Morse Code
*/
public static MorseString convert(String s) {
// ...
return new MorseString(convertedString);
}
So, if you have a valid line of Morse code, you use the constructor to turn it into an object. However, if you have data that needs transformation, you call the static factory method:
MorseString ms = MorseString.convert(myString);
source to share
Yes. Get rid of your constructors and use a different approach instead, like
1) A Factory Method , so you will have methods like this:
class MorseString {
private MorseString(){};
public static MorseString getFromCode(String s) {
// ...
}
public static MorseString getFromString(String s) {
// ...
}
}
// Usage: MorseString.getFromCode(foo);
or
2) A Builder , so you will have methods like this
class MorseString {
private MorseString(){};
static class Builder {
Builder initFromCode(String code) {
// ..
return this;
}
Builder initFromString(String str) {
// ..
return this;
}
MorseString build() {
// ..
}
}
}
// Usage: MorseString.Builder.initFromCode(foo).build();
A constructor is good if you have very complex creation logic, many parameters, objects with some part of their information in the middle of creation, some preliminary checks, etc. A factory method is an easier approach for a situation where you have multiple ways to create an object with slightly varying parameters.
source to share