简体   繁体   English

是否可以使两个Java接口互斥?

[英]Is it possible to make two Java interfaces mutually exclusive?

I have two interfaces that should exclude each other: 我有两个应该相互排斥的接口:

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

How can I prevent the implementation of a class that implements both Cat and Bird interfaces? 如何防止实现同时实现CatBird接口的类?

class Impossible implements Cat, Bird{}

Finally a dirty solution: 最后一个肮脏的解

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 cant be implemented because: CatBird无法实施,因为:

The interface Animal cannot be implemented more than once with different arguments: Animal<Bird> and Animal<Cat> 接口Animal不能使用不同的参数多次实现:Animal <Bird>和Animal <Cat>

Here you have a clear hierarchy - a root with branches, and clearly a node (class, interface, whatever) cannot be on more than one branch. 在这里你有一个清晰的层次结构 - 一个带分支的根,很明显一个节点(类,接口,等等)不能在多个分支上。 In order to enforce this, use abstract classes instead of interfaces. 为了强制执行此操作,请使用抽象类而不是接口。

Interfaces may be used when there is some cross-cutting aspect which may be shared between any of the classes in your hierarchy, and where no two interfaces are mutually exclusive. 当存在某些交叉方面时可以使用接口,这些方面可以在层次结构中的任何类之间共享,并且没有两个接口是互斥的。

example: 例:

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

At least one other has considered this problem: http://instantbadger.blogspot.co.uk/2006/10/mutually-exclusive-interfaces.html 至少有一个人考虑过这个问题: http//instantbadger.blogspot.co.uk/2006/10/mutually-exclusive-interfaces.html

The interfaces in Java are born to be implemented. Java中的接口已经诞生了。 Any class can implement any interface as long as it wants. 任何类都可以实现任何接口,只要它想要。 So, I think there is no way to prevent that case. 所以,我认为没有办法阻止这种情况。 You probably need reconsider your design. 您可能需要重新考虑您的设计。

There is a really, really ugly workaround. 有一个非常非常丑陋的解决方法。 Implement a conflicting method signature to Cat and Bird interfaces: 为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 {
}

But don't do this. 但是不要这样做。 Figure out a better way instead. 找出一个更好的方法。

probably you can not prevent. 可能你无法阻止。 maybe you can replace Cat and Bird by an abstract class and the Impossible can only extends one. 也许你可以用一个抽象的类代替CatBird ,而Impossible只能扩展一个。

Not sure if this helps, but if you do not specify that the interface is public, your interface will be accessible only to classes defined in the same package as the interface. 不确定这是否有帮助,但是如果您没有指定接口是公共的,那么只有与接口在同一个包中定义的类才能访问您的接口。

So essentially, you could put your interface in one package, and any classes that you don't want to be able to implement it in another.. 基本上,您可以将您的界面放在一个包中,以及任何您不希望能够在另一个包中实现它的类。

Java does not provide a piece of syntax that will prevent one class from implementing two different interfaces. Java没有提供一种语法来阻止一个类实现两个不同的接口。 This is a good thing, because interfaces are supposed to let you forget about exactly what object you're dealing with and focus on just the functionality associated with that interface. 这是一件好事,因为接口应该让你忘记你正在处理的对象,并专注于与该接口相关的功能。

In the case of animals this can seem confusing, because in real life no animal is both a cat and a dog. 在动物的情况下,这似乎令人困惑,因为在现实生活中,没有动物是猫和狗。 But there is no reason that one Java class cannot fulfil the contract of both a Cat interface and a Dog interface. 但是没有理由说一个Java类不能满足Cat接口和Dog接口的契约。 If you want to ground this in reality, consider a box containing both a cat and a dog! 如果你想在现实中解决这个问题,可以考虑一个包含猫和狗的盒子!

Now, as Torben and others point out, you can deliberately introduce methods into an interface that will clash with methods in the other interface. 现在,正如Torben和其他人指出的那样,你可以故意将方法引入到与其他接口中的方法冲突的接口中。 This will cause Java to forbid both interfaces being implemented in one class. 这将导致Java禁止在一个类中实现两个接口。 But for the reasons listed above, this is not a good work-around to consider. 但由于上面列出的原因,这不是一个好的解决方案。

The best approach if you must force this relationship is the answer provided by NickJ . 如果你必须强迫这种关系,最好的方法是NickJ提供的答案

You many throw an exception when a class is going to use it, the UML Diagram would like this 当一个类要使用它时,你会抛出异常,UML Diagram会喜欢这个
在此输入图像描述
as you see in the above, the Possible would implement either Cat or Bird , but not both. 正如你在上面看到的那样, Possible会实现CatBird ,但不能同时实现两者。 but this is just a diagram, so the functionality would be like this. 但这只是一个图表,所以功能就是这样。

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);
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM