将字符串的特定"类型"传递给函数的"最佳实践"方法是什么?

Spy*_*cho 3 java

例如,我有一个有两个字符串的类,其中一个必须设置,另一个可以为null:

public class SomeClass{
    private String s1;
    private String s2;

    ...
}
Run Code Online (Sandbox Code Playgroud)

我可以定义一个构造函数如下:

public SomeClass(String s1, String s2){
    if(s1 == null && s2 == null) throw new SomeKindOfException("can't both be null");

    this.s1 = s1;
    this.s2 = s2;
}
Run Code Online (Sandbox Code Playgroud)

我宁愿做一些事情:

public SomeClass(String s1){
    this.s1 = s1;
}

public SomeClass(String s2){
    this.s2 = s2;
}
Run Code Online (Sandbox Code Playgroud)

这显然无法工作,因为它定义了两个采用相同数量和类型的参数的方法.

所以,我想做的事情如下:

public SomeClass(SomeTypeOfString s1){
    this.s1 = s1;
}

public SomeClass(AnotherTypeOfString s2){
    this.s2 = s2;
}
Run Code Online (Sandbox Code Playgroud)

这具有额外的优点,即String的"类型"可以验证它们的内容(例如,SomeTypeOfString必须是6个字符长,而AnotherTypeOfString必须在4到8个字符长之间并且仅包含字母数字字符.

此外,它在调用函数时更清楚,应传入哪些数据.

首先,这个概念听起来合情合理吗?

在实现方面,您无法扩展String.你可以把它包起来.String的"类型"本质上是String的类型,因此让它们扩展抽象包装类是有意义的.这可以实现如下:

public abstract class StringWrapper{
    private final String string;

    public StringWrapper(String string){
        this.string = string;
    }

    public String getString(){
        return string;
    }
}

public class SomeTypeOfString extends StringWrapper{
    public SomeTypeOfString(String string){
        super(string);
    }
}
Run Code Online (Sandbox Code Playgroud)

SomeTypeOfString类的代码看起来相当愚蠢,因为它所做的只是定义一个调用超类构造函数的构造函数......但假设你还在那里添加了一些验证,对我来说它看起来很合理.这种实现听起来合理吗?

谁能想到一个更好的概念来解决基本问题,或者更好地实现我概述的概念?

Kev*_*vin 5

您可以使用构建器.即

public SomeClassBuilder {
    String s1;
    String s2;
    public SomeClassBuilder someString1(String s) {
        this.s1 = s;
        return this;
    }
    public SomeClassBuilder someString2(String s) {
        this.s2 = s;
        return this;
    }
    public SomeClass build() {
        SomeClass sc = new SomeClass();

        // if one of s1 or s2 must be null, or you have some other sort of validation, you could do that here, e.g.
        if (s1 != null && s2 != null) throw new RuntimeException("not what I expected");
        else if (s1 == null && s2 == null) throw new RuntimeException("at least set one value");
        sc.setS1(s1);
        sc.setS2(s2);
        return sc;
    }

}
Run Code Online (Sandbox Code Playgroud)

用法是:

   SomeClass sc = new SomeClassBuilder().someString1("xxx").someString2("yyy").build();
Run Code Online (Sandbox Code Playgroud)

要么:

  SomeClass sc = new SomeClassBuilder().someString2("abc").build();
Run Code Online (Sandbox Code Playgroud)

对于仅两个构造函数参数,益处相对较小,但随着输入的增加,可读性益处增加.