11

我有两个应该相互排除的接口:

interface Animal{}
interface Cat extends Animal{}
interface Bird extends Animal{}

如何防止实现同时实现CatBird接口的类的实现?

class Impossible implements Cat, Bird{}
4

8 回答 8

11

最后一个肮脏的解决方案:

public interface Animal<BEING extends Animal> {}
public interface Cat extends Animal<Cat> {}
public interface Bird extends Animal<Bird> {}
public class CatBird implements Cat, Bird {} // compiler error
public interface CatBird extends Cat, Bird {} // compiler error

CatBird 无法实施,因为:

接口 Animal 不能使用不同的参数多次实现:Animal<Bird> 和 Animal<Cat>

于 2013-10-29T16:33:45.800 回答
8

在这里,您有一个清晰的层次结构 - 一个带有分支的根,并且显然一个节点(类、接口等)不能位于多个分支上。为了强制执行这一点,请使用抽象类而不是接口。

当层次结构中的任何类之间可以共享某些横切方面,并且没有两个接口相互排斥时,可以使用接口。

例子:

public abstract class Animal;
public interface CanFly;
public interface CanHunt;
public abstract class Cat extends Animal implements CanHunt;
public abstract class Bird extends Animal implements CanFly;
public class Vulture extends Bird implements CanHunt; //also CanFly because of Bird

至少有其他人考虑过这个问题:http: //instantbadger.blogspot.co.uk/2006/10/mutually-exclusive-interfaces.html

于 2013-10-25T09:23:12.383 回答
3

Java 中的接口是为实现而生的。任何类都可以实现任何接口,只要它愿意。所以,我认为没有办法阻止这种情况。您可能需要重新考虑您的设计。

于 2013-10-25T09:13:42.850 回答
3

有一个非常非常丑陋的解决方法。对 Cat 和 Bird 接口实现冲突的方法签名:

public interface Cat {
    int x();
}

public interface Bird {
    float x();
}

/**
 * ERROR! Can not implement Cat and Bird because signatures for method x() differ!
 */
public class Impossible implements Cat, Bird {
}

但不要这样做。想出一个更好的方法。

于 2013-10-25T09:17:35.373 回答
2

可能你无法阻止。也许您可以用一个抽象类替换Catand Bird,而 Impossible 只能扩展一个。

于 2013-10-25T09:14:30.460 回答
1

不确定这是否有帮助,但如果您没有指定接口是公共的,那么您的接口将只能被定义在与接口相同的包中的类访问。

所以本质上,你可以把你的接口放在一个包中,而你不想在另一个包中实现它的任何类..

于 2013-10-25T09:30:27.423 回答
0

Java 没有提供阻止一个类实现两个不同接口的语法。这是一件好事,因为接口应该让您忘记您正在处理的确切对象,而只关注与该接口相关的功能。

就动物而言,这似乎令人困惑,因为在现实生活中,没有任何动物既是猫又是狗。但是没有理由一个 Java 类不能同时履行Cat接口和Dog接口的契约。如果您想在现实中实现这一点,请考虑一个包含猫和狗的盒子!

现在,正如 Torben 和其他人所指出的,您可以故意将方法引入一个接口,这将与另一个接口中的方法发生冲突。这将导致 Java 禁止在一个类中实现两个接口。但是由于上面列出的原因,这不是一个很好的解决方法。

如果您必须强制这种关系,最好的方法是NickJ 提供的答案

于 2013-10-25T09:14:27.093 回答
0

当一个类要使用它时,很多人会抛出一个异常,UML 图就像
在此处输入图像描述
你在上面看到的那样,Possible将实现一个CatBird,但不能同时实现两者。但这只是一个图表,所以功能应该是这样的。

interface Animal{void x();}
interface Cat extends Animal{}
interface Bird extends Animal{}
class Impossible implements Cat, Bird{

  @Override
  public void x() {
    System.out.println("Oops!");    
  }}

class Possible implements Cat{

  @Override
  public void x() {
    System.out.println("Blah blah");    
  }

}
class Core {
  private Animal a;
  public void setAnimal(Animal a) throws Exception {
    if (a instanceof Cat && a instanceof Bird) {
      System.out.println("Impossible!");
      throw new Exception("We do not accept magic");
    }
    this.a = a;
    a.x();
  }
  public static void main(String[] args) throws Exception {
    Core c = new Core();
    Possible p = new Possible();
    c.setAnimal(p);
    Impossible ip = new Impossible();
    c.setAnimal(ip);
  }
}
于 2013-10-25T09:25:36.543 回答