4

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

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
    }
}
4

5 回答 5

3

现在我可以将 UserLogic 转换为两个接口中的任何一个,并检索一组不同的异常!

不,你不能。请参阅 Joshua Bloch 和 Neal Gafter 撰写的“Java Puzzlers:Traps, Pitfalls, and Corner Cases”,Puzzle 37 Exceptionally Arcane:

每个接口都限制了方法可以抛出的检查异常的集合。方法可以抛出的已检查异常集是声明为在所有适用类型中抛出的已检查异常集的交集,而不是联合。

所以在你的情况下实施

创建(用户用户)抛出异常继承

是正确的。但

创建(用户用户)抛出 ExceptionSuper

不会编译

于 2012-10-06T14:24:38.163 回答
2

您不会收到不同的异常,因为ExceptionInheritextends 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不连接。在这种情况下,您将收到一个编译错误,因为它ExceptionA与.throwsY

于 2012-10-06T14:18:58.693 回答
1

它可以在没有泛型的情况下工作,也没有例外。甚至可以追溯到 Java 1.4,而且可能更早。

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

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

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

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

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

有效代码:

public interface IDo {
    public void does();
}


public interface ITwo {
    public void does();
}

public class Test implements IDo, ITwo {
public void does() {
}
}
于 2012-10-06T15:12:41.620 回答
1
I always thought that two interfaces with the same method cannot 
be inherited by one class, as stated in many so questions.

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

如果一个类使用这样的方法实现两个或多个接口,那很好,前提是:

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

例如:

interface A {
    Integer x();
}

interface B {
    Number x();
}

interface C {
    Object x();
}

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

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

因此,您提供的示例符合这些规则,并且完全可以执行。

于 2012-10-06T17:12:01.327 回答
0

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

可以使用“ExceptionInherit”对象代替“ExceptionSuper”对象,因为它继承自它。“ExceptionInherit”对象具有“ExceptionSuper”对象所做的所有信息(以及更多信息)。反过来,情况并非如此。您不能使用“ExceptionSuper”对象代替“ExceptionInherit”对象,因为“ExceptionInherit”代码期望的比您的基本对象拥有的更多(好吧,可能但不是您的情况)。

您对“create”方法的实现填充了 ICreateUser“create”签名,因为它抛出了一个“ExceptionInherit”,可以将其抛出给“ExceptionInherit”和“ExceptionSuper”的捕获器,从中获取他们需要的所有信息(只是基类)物体。

你不能改变你的实现来抛出一个“ExceptionSuper”,因为期待一个“ExceptionInherit”的捕手会得到一个没有足够信息的对象。

于 2012-10-06T14:39:38.567 回答