Java - 具有相同方法的两个接口,一个只是通用的

时间:2012-10-06 14:09:02

标签: java interface polymorphism

我一直认为具有相同方法的两个接口不能被一个类继承,正如很多问题所述。

Java jre 7,jdk 1.7

但这里的代码正在运作。

示例:

接口

public interface IObject
{
    public Object create(Object object) throws ExceptionInherit;
}

public interface IGeneric<T>
{
    public T create(T t) throws ExceptionSuper;
}

实施课程:

public class Test implements IGeneric<Object>, IObject
{
    @Override
    public Object create(final Object object) throws ExceptionInherit
    {
        return object;
    }
}

这两个方法声明是否具有相同的主体?

例外:

例外只是这个结构的附加物,使其更加复杂。

public class ExceptionSuper extends Exception {}
public class ExceptionInherit extends ExceptionSuper {}

它也没有任何抛出异常。

进一步:如果两个方法接口抛出不同的继承异常,我可以将UserLogic强制转换为两个接口中的任何一个,并检索异常的不同子集!

为什么这有效?

修改

The generic implementation is not even necessary:

public interface IA
{
    public void print(String arg);
}

public interface IB
{
    public void print(String arg);
}

public class Test implements IA, IB
{
    @Override
    public void print(String arg);
    {
        // print arg
    }
}

5 个答案:

答案 0 :(得分:3)

  

现在我可以将UserLogic转换为两个接口中的任何一个并检索一个   不同的例外情况!

不,你不能。请参阅Joshua Bloch和Neal Gafter撰写的“Java Puzzlers:陷阱,陷阱和角落案例”,Puzzle 37 Exceptionally Arcane:

  

每个接口都限制方法可以执行的已检查异常集   扔。方法可以抛出的一组已检查异常是   声明它的已检查异常集的交集   扔掉所有适用的类型,而不是工会。

所以在你的案例实现中

  

create(用户用户)抛出ExceptionInherit

是对的。但

  

create(用户用户)抛出ExceptionSuper

不会编译

答案 1 :(得分:2)

由于ExceptionInherit扩展ExceptionSuper,您不会收到不同的例外情况。但请考虑一下:

interface X {
    public void foo() throws ExceptionA;
}

interface Y {
    public void foo() throws ExceptionB;
}

class ExceptionA extends Exception {}
class ExceptionB extends Exception {}

class Z implements X, Y {
    public void foo() throws ExceptionA {

    }
}

请注意ExceptionAExceptionB未通过继承进行连接。在这种情况下,您将收到编译错误,因为ExceptionAthrows中的Y子句不兼容。

答案 2 :(得分:1)

没有通用,它也可以工作,没有例外。甚至可以追溯到Java 1.4,也可能在之前。

  

我一直认为具有相同方法的两个接口不能被一个类继承,正如很多问题所述。

实际上这不是真的,我不确定你指的是什么问题。

当然有理由不使用具有相同方法签名的两个接口,最重要的一个是实现只能做一件事,所以如果两个接口都期望从方法得到不同的结果,你将无法满足两个接口,但这不会是编译错误。

还有一些原因使得具有相同方法的2个接口完全有效。如果2个接口相互扩展,则实现可以很好地实现两个接口。即使在接口只是共享名称的简单情况下,也没有技术限制。

接口只请求某些方法可用,它不要求其他接口不存在。

有效代码:

public interface IDo {
    public void does();
}


public interface ITwo {
    public void does();
}

public class Test implements IDo, ITwo {
public void does() {
}
}

答案 3 :(得分:1)

I always thought that two interfaces with the same method cannot 
be inherited by one class, as stated in many so questions.

如果你想更精确,你应该用“具有覆盖等效签名的方法”替换“相同方法”。签名是“方法名称”+“参数列表”(某些规则也适用于返回类型和throws子句)。你需要知道覆盖等价的确切含义。

如果一个类使用这样的方法实现两个或更多接口,那就完全没问题了:

1-它们都具有相同的返回类型,或者其中一个方法的返回类型是所有其他方法的子类型。这是您应该在实现中使用的返回类型。

例如:

interface A {
    Integer x();
}

interface B {
    Number x();
}

interface C {
    Object x();
}

class Foo implements A, B, C
{
    Integer x() { 
        //...
    }
}

2-实现必须满足每个超级接口声明的所有此类方法的throws子句。

所以你给出的例子都遵循这些规则,并且完全没问题。

答案 4 :(得分:0)

你绝对可以“实现”两个具有相同签名方法的接口。您在尝试“扩展”具有相同方法实现的两个类时遇到了麻烦。多接口继承是好的;多实现继承是TRICKY。

可以使用“ExceptionInherit”对象代替“ExceptionSuper”对象,因为它继承了它。 “ExceptionInherit”对象具有“ExceptionSuper”对象所具有的所有信息(以及更多)。反之亦然。您不能使用“ExceptionSuper”对象代替“ExceptionInherit”对象,因为“ExceptionInherit”代码需要的内容多于您的基础对象(嗯,可能但不是您的情况)。

你的“create”方法的实现填充了ICreateUser“create”签名,因为它抛出了一个“ExceptionInherit”,可以抛出“ExceptionInherit”和“ExceptionSuper”的捕获者获取他们需要的所有信息(只是基础)来自对象的。)

你无法改变你的实现以抛出“ExceptionSuper”,因为捕获者期望“ExceptionInherit”会得到一个信息不足的对象。