Java 如何在不使用固有性的情况下将两个不相关的类合并为一个类型

Java 如何在不使用固有性的情况下将两个不相关的类合并为一个类型,java,design-patterns,Java,Design Patterns,我有两个类:X和Y。它们都不相关或具有相同的属性。 但是还有另一个类Z,它有setter和getter,setter可以接受X或Y类型,getter可以返回X或Y类型。 我想为x,y创建一个父类parent,并将其用作setter和getter的类型。。但我不认为这是一个好的设计,会打破固有的全部意义。 在这种情况下我能做什么?除了对z类使用泛型类型“T”之外,如果一个方法有时返回不同的类型,则可能需要重写代码。您应该始终返回相同的类型 通常,重新排列代码就足够了,但并不总是这样,这时实现某种包

我有两个类:X和Y。它们都不相关或具有相同的属性。 但是还有另一个类Z,它有setter和getter,setter可以接受X或Y类型,getter可以返回X或Y类型。 我想为x,y创建一个父类parent,并将其用作setter和getter的类型。。但我不认为这是一个好的设计,会打破固有的全部意义。
在这种情况下我能做什么?除了对z类使用泛型类型“T”之外,如果一个方法有时返回不同的类型,则可能需要重写代码。您应该始终返回相同的类型


通常,重新排列代码就足够了,但并不总是这样,这时实现某种包含嵌套对象的容器对象(纯粹是为了返回它们)就很常见了。

如果一个方法有时返回不同的类型,您可能需要重写代码。您应该始终返回相同的类型

通常,重新排列代码就足够了,但并不总是这样,这时实现某种包含嵌套对象的容器对象通常只是为了返回它们。

免责声明 正如其他人已经指出的,这首先是设计拙劣的标志,而且气味难闻

考虑重新设计代码,这样就不需要同时返回两个不相关的东西


密码 无论如何,这里有一些代码可以实现这种情况的解决方案。我们正在使用一个提供getter的
容器
类。但其中只有一个有效,因此也有方法来检查哪一个有效。这样的类通常称为
Union
Variant
,因为只允许包含其中一种类型

public class Variant<X, Y> {
    public static <X, Y> Variant<X, Y> ofX(X x) {
        Objects.requireNonNull(x);
        return new Variant(x, null);
    }

    public static <X, Y> Variant<X, Y> ofY(Y y) {
        Objects.requireNonNull(y);
        return new Variant(null, y);
    }

    private final X x;
    private final Y y;

    private Variant(X x, Y y) {
        this.x = x;
        this.y = y;
    }

    public X getX() {
        if (x == null) {
            throw new IllegalStateException("Contains the other type");
        }
        return x;
    }

    public Y getY() {
        if (y == null) {
            throw new IllegalStateException("Contains the other type");
        }
        return y;
    }

    public boolean isX() {
        return x != null;
    }

    public boolean isY() {
        return y != null;
    }
}
公共类变量{
公共静态变量X(X X){
对象。requirennull(x);
返回新变量(x,null);
}
Y(Y)的公共静态变量{
对象。要求不完整(y);
返回新变量(空,y);
}
私人决赛X X;
私人决赛;
专用变量(X、Y、Y){
这个.x=x;
这个。y=y;
}
公共X getX(){
如果(x==null){
抛出新的IllegalStateException(“包含其他类型”);
}
返回x;
}
公共场所{
如果(y==null){
抛出新的IllegalStateException(“包含其他类型”);
}
返回y;
}
公共布尔isX(){
返回x!=null;
}
公共布尔值isY(){
返回y!=null;
}
}
用法:

Variant<String, Integer> variant1 = Variant.ofX("hello");
System.out.println(variant1.getX()); // hello

Variant<String, Integer> variant2 = Variant.ofY(20);
System.out.println(variant2.getY()); // 20
variant1=Variant.ofX(“你好”);
System.out.println(variant1.getX());//你好
变量variant2=变量y(20);
System.out.println(variant2.getY());//20
或者在您的具体示例中:

public Variant<String, Integer> foo() {
    ...
    if (...) {
        return Variant.ofX("hello");
    } else {
        return Variant.ofY(20);
    }
}
public Variant foo(){
...
如果(…){
返回Variant.ofX(“hello”);
}否则{
返回变量y(20);
}
}

笔记 使用静态工厂方法的目的是为了让两个不同的构造函数具有
X
Y
,只有在类型擦除后才会产生相同的签名。因此,需要两个不同的方法名

在“可选-所有BiksHeDS的母亲”的颂歌中,您可能还想考虑重命名<代码> GETX()/<代码>和<代码> GETYY()>代码>到更严肃的事情,如<代码> GETXCORGROW()< <代码> >代码> GETYORLROWE()/<代码> < /P>免责声明。 正如其他人已经指出的,这首先是设计拙劣的标志,而且气味难闻

考虑重新设计代码,这样就不需要同时返回两个不相关的东西


密码 无论如何,这里有一些代码可以实现这种情况的解决方案。我们正在使用一个提供getter的
容器
类。但其中只有一个有效,因此也有方法来检查哪一个有效。这样的类通常称为
Union
Variant
,因为只允许包含其中一种类型

public class Variant<X, Y> {
    public static <X, Y> Variant<X, Y> ofX(X x) {
        Objects.requireNonNull(x);
        return new Variant(x, null);
    }

    public static <X, Y> Variant<X, Y> ofY(Y y) {
        Objects.requireNonNull(y);
        return new Variant(null, y);
    }

    private final X x;
    private final Y y;

    private Variant(X x, Y y) {
        this.x = x;
        this.y = y;
    }

    public X getX() {
        if (x == null) {
            throw new IllegalStateException("Contains the other type");
        }
        return x;
    }

    public Y getY() {
        if (y == null) {
            throw new IllegalStateException("Contains the other type");
        }
        return y;
    }

    public boolean isX() {
        return x != null;
    }

    public boolean isY() {
        return y != null;
    }
}
公共类变量{
公共静态变量X(X X){
对象。requirennull(x);
返回新变量(x,null);
}
Y(Y)的公共静态变量{
对象。要求不完整(y);
返回新变量(空,y);
}
私人决赛X X;
私人决赛;
专用变量(X、Y、Y){
这个.x=x;
这个。y=y;
}
公共X getX(){
如果(x==null){
抛出新的IllegalStateException(“包含其他类型”);
}
返回x;
}
公共场所{
如果(y==null){
抛出新的IllegalStateException(“包含其他类型”);
}
返回y;
}
公共布尔isX(){
返回x!=null;
}
公共布尔值isY(){
返回y!=null;
}
}
用法:

Variant<String, Integer> variant1 = Variant.ofX("hello");
System.out.println(variant1.getX()); // hello

Variant<String, Integer> variant2 = Variant.ofY(20);
System.out.println(variant2.getY()); // 20
variant1=Variant.ofX(“你好”);
System.out.println(variant1.getX());//你好
变量variant2=变量y(20);
System.out.println(variant2.getY());//20
或者在您的具体示例中:

public Variant<String, Integer> foo() {
    ...
    if (...) {
        return Variant.ofX("hello");
    } else {
        return Variant.ofY(20);
    }
}
public Variant foo(){
...
如果(…){
返回Variant.ofX(“hello”);
}否则{
返回变量y(20);
}
}

笔记 使用静态工厂方法的目的是为了让两个不同的构造函数具有
X
Y
,只有在类型擦除后才会产生相同的签名。因此,需要两个不同的方法名

在“可选-所有BiksHeDS的母亲”的颂歌中,您可能还想考虑重命名<代码> GETX()/<代码>和<代码> GETYY()>代码>到更严肃的事情,如<代码> GETXCURROWE()< <代码> >代码> GETyCyRoWo()/<代码> < /P>