Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 方法返回为接口_Java - Fatal编程技术网

Java 方法返回为接口

Java 方法返回为接口,java,Java,考虑这个例子: 我有3个接口:A,B,C,方法A(),B(),C();扩展基本接口Intf 我有一个带有选项MyEnum.a、MyEnum.B、MyEnum.C的枚举 我有一个类扩展了这3个接口:X实现了a、B、C 有一种方法可以在X中实现这样的方法 public <T extends Intf> T getType (MyEnum enum) 或 但从来没有 X var = X.getType(MyEnum.A).b("value").build(); //ERROR 假设我们

考虑这个例子:

我有3个接口:A,B,C,方法A(),B(),C();扩展基本接口Intf

我有一个带有选项MyEnum.a、MyEnum.B、MyEnum.C的枚举

我有一个类扩展了这3个接口:X实现了a、B、C

有一种方法可以在X中实现这样的方法

public <T extends Intf> T getType (MyEnum enum)

但从来没有

X var = X.getType(MyEnum.A).b("value").build(); //ERROR

假设我们在类X中,您有一个本地泛型参数,您可以考虑:

public <T extends Intf> T getType (MyEnum enumVal) {
  if (enumVal == MyEnum.A) {
    return (A) this;
  if (enumVal == MyEnum.B) {
    return (B) this;
但你也可以写

B someB = whatever.getType(someEnum);
使用非常相同的
someEnum
。编译器会很高兴的


如果您想在“编译时安全性”方面有所收获,您必须以某种方式将参数类型“连接”到结果类型

您可以分派枚举值,并返回一个匹配的实例,正如@GhostCat所建议的那样

您还可以反转查找,以便每个枚举值提供一个适当的
Intf
实例:

变体1:每个枚举值的单实例

public enum MyEnum {

    A(new AImpl()),
    B(new BImpl()),
    C(new CImpl());

    private Intf instance;

    MyEnum2(Intf instance) {
        this.instance = instance;
    }

    public <T extends Intf> T getType() {
        return (T) instance;
    }
}

如果我没看错你的问题,你希望编译时安全

public <T extends Intf> T getType (MyEnum enum)
现在,类
TT
实现了所有这些接口:

public class TT implements AA, BB, CC {

    @Override
    public void a() { ... }

    @Override
    public void b() { ... }

    @Override
    public void c() { ... }

}
现在让
EE
成为我们的通用伪枚举类,用
II
的某些子类型参数化:

public interface AA extends II { void a(); }
public interface BB extends II { void b(); }
public interface CC extends II { void c(); }
public class EE<XX extends II> {

    public static final EE<AA> A = new EE<AA>();
    public static final EE<BB> B = new EE<BB>();
    public static final EE<CC> C = new EE<CC>();

}
此方法只能返回参数化
enumVal
的类型。意义

AA type = tt.getType(EE.A);
有效,但

BB type = tt.getType(EE.A);
事实并非如此

实现
getType
方法的方法之一是将
TT
实例的“转换”委托给
AA
BB
CC
给相应的伪枚举:

public abstract class EE<XX extends II> {

    public static final EE<AA> A = new EE<AA>() {
        @Override
        public <PP extends AA & BB & CC> AA convert(PP instance) {
            return new AA() {
                public void a() {
                    instance.a();
                };
            };
        }
    };
    public static final EE<BB> B = new EE<BB>() {
        @Override
        public <PP extends AA & BB & CC> BB convert(PP instance) {
            return new BB() {
                public void b() {
                    instance.b();
                };
            };
        }
    };
    public static final EE<CC> C = new EE<CC>() {
        @Override
        public <PP extends AA & BB & CC> CC convert(PP instance) {
            return new CC() {
                public void c() {
                    instance.c();
                };
            };
        }
    };

    public abstract <PP extends AA & BB & CC> XX convert(PP instance);
}
据我所知,编译器不允许

BB bb = tt.getType(EE.A);

不会像“在运行时生成
ClassCastException
中那样工作”


缺点是伪枚举构造和
convert

的有些丑陋的实现。我不确定第一个要求:目前我假设baseInterface Intf有3个方法a()、b()和c()。但当我继续阅读时,我不确定是否是这样。请不要解释代码,展示它。请准确地说明您希望如何使用/调用方法
getType(…)
。代码最好用最少的代码示例来解释!我猜OP想要
getType(MyEnum.A)
返回
A
的实例,
getType(MyEnum.B)
返回
B
的实例等,也就是说,用方法签名来表示。像
public T getType(MyEnum)
这样的签名没有意义。签名上写着“无论打电话的人想要什么,我都会退还”。您甚至可以说
String s=X.getType(…)
。当然,
String
不会实现
Intf
,但是可能有一个类型扩展了
String
并实现了
Intf
,并且您的方法很难实现这个承诺并返回这样一个类型的实例,尤其是
String
final
…我想在一个具有流畅api的构建器上使用它:X.getType(MyEnum.a).a().build()或X.getType(MyEnum.B).B().build(),但永远不要使用X.getType(MyEnum.a).B().build()@marciel.deg,因为这个注释并不能真正阐明您的需求。正如其他人所说:请编辑您的问题,使之更加具体!那些演员对打电话的人来说无关紧要你可以将
这个
包装成
a
B
C
的一个新的(匿名内部类)实例,只提供对
a()
B()
C()
的访问权限。你得到了我的投票支持,同意在这里提出一个想法@AxelH你说得对,我没有注意到A、B、C也是接口。编辑我的答案以提供那些接口的实现,感谢您的提示。但是编译器不会拒绝编写
A A=MyEnum.C.getType()
cc=MyEnum.A.getType()。当泛型代码在运行时甚至不会立即失败时,情况可能会变得更糟,但会导致堆污染、错误类型的实例存储在某个地方,而当没有人知道对象来自何处时,这些实例将在更晚的时间失败。想想
Set someMethod(){return Collections.singleton(MyEnum.B.getType());}
…这个答案接近我需要的。@marciel.deg如果你觉得我的答案对你有帮助,你可以。
public class EE<XX extends II> {

    public static final EE<AA> A = new EE<AA>();
    public static final EE<BB> B = new EE<BB>();
    public static final EE<CC> C = new EE<CC>();

}
public <XX extends II> XX getType(EE<XX> enumVal)
AA type = tt.getType(EE.A);
BB type = tt.getType(EE.A);
public abstract class EE<XX extends II> {

    public static final EE<AA> A = new EE<AA>() {
        @Override
        public <PP extends AA & BB & CC> AA convert(PP instance) {
            return new AA() {
                public void a() {
                    instance.a();
                };
            };
        }
    };
    public static final EE<BB> B = new EE<BB>() {
        @Override
        public <PP extends AA & BB & CC> BB convert(PP instance) {
            return new BB() {
                public void b() {
                    instance.b();
                };
            };
        }
    };
    public static final EE<CC> C = new EE<CC>() {
        @Override
        public <PP extends AA & BB & CC> CC convert(PP instance) {
            return new CC() {
                public void c() {
                    instance.c();
                };
            };
        }
    };

    public abstract <PP extends AA & BB & CC> XX convert(PP instance);
}
public <XX extends II> XX getType(EE<XX> enumVal) {
    return enumVal.convert(this);
}
BB bb = tt.getType(EE.A);
BB bb = (BB) tt.getType(EE.A);
bb.b();