java.lang.Boolean is perfect to handle trinary logic, because it can exactly have three states: Boolean.TRUE (it is the case that), Boolean.FALSE (it is not the case that) and null (we don't know what the case is). It would be a nice design to handle this using switch statements, eg. in this constructor:
public class URN {
private String value = null;
public URN (String value, Boolean mode){
switch (mode){
case TRUE:
if(!isValidURN(value))
throw new MalformedURLException("The string could not be parsed.");
this.value = value;
break;
case FALSE:
this.value = value.concat(checkByteFor(value));
break;
case null:
if(isValidURN(value))
this.value = value;
else
this.value = value.concat(checkByteFor(value));
break;
}
return;
}
Unluckily, Java doesn't allow that, complaining "Cannot switch on a value of type Boolean." Implementing this results in an obfuscated control flow and unnice code:
public URN (String value, Boolean mode){
Boolean valid = null;
if (!Boolean.FALSE.equals(mode)){
valid = isValidURN(value);
if (Boolean.TRUE.equals(mode) && !valid)
throw new MalformedURLException("The string could not be parsed.");
if(Boolean.TRUE.equals(valid)) {
this.value = value;
return;
} }
this.value = value.concat(checkByteFor(value));
}
Doing it the nice way requires to implement an enum class (which, in real life, is more complex than in this example, because .equals() must be rewritten so that Trinary.NULL.equals(null) becomes true) and converting:
private enum Trinary {TRUE, FALSE, NULL};
public URN (String value, Boolean toConvert, String x){
Trinary mode;
if(toConvert == null)
mode = Trinary.NULL;
else
mode = toConvert.equals(Boolean.TRUE) ? Trinary.TRUE : Trinary.FALSE;
switch (mode){
case TRUE:
if(!isValidURN(value)) throw new MalformedURLException("The string could not be parsed.");
this.value = value;
break;
case FALSE:
this.value = value.concat(checkByteFor(value));
break;
case NULL:
if(isValidURN(value))
this.value = value;
else
this.value = value.concat(checkByteFor(value));
break;
}
return;
}
To my eyes, this is the better since more readable solution, but the another half of the origin method size of code just to convert is annoying, and in real life you have to care about two different nulls with the same semantic. Is there a better way to do it?
Using a null object to convey information like this is not optimal. Remember that you cannot do any method calls on a null object, which again would mean that if you in the future ever would want to call any .getClass, .equals, .compare etc., you would have to rewrite your code.
Your best option is definitely to go with the enum option.
enum Ternary {TRUE,FALSE,UNKNOWN}
You can furthermore expand the class to have a method of getting such object,
public Ternary getByValue(Boolean o) {
if(o == null)
return UNKNOWN;
if(o)
return TRUE;
return FALSE;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With