将字段限制为类的实例并同时实现接口

时间:2013-03-13 17:14:43

标签: java oop

Java允许将子类实例分配给类类型字段,例如:

public class BaseClass {

}

public class SubClass extends BaseClass {

}

public class Example {

    private BaseClass field1;

    public void assign(SubClass subclass) {
        field1 = subclass; // is OK
    }

}

Java还允许将接口用作类型。如果我们有一个接口Fooable

public interface Fooable {
    void foo();
}

我们的Example类可以包含Fooable类型的字段,

    Fooable field2;

也就是说,可以为field2分配实现Fooable接口的任何类的实例。

但是如果我想告诉编译器field3必须 BaseClass的实例和Fooable接口的实现呢?所以,如果有一个类

public class FooSubClass extends BaseClass implements Fooable {
    @Override
    public void foo() {
        // TODO
    }
}

,我可以分配给field3 FooSubClass但不是SubClass的实例? 是否可以不使用任何类型的泛型

3 个答案:

答案 0 :(得分:8)

你不能像你想要的那样去做。

您需要定义另一个类,也许这里的抽象类适合您:

public class abstract AbstractSubClass extends BaseClass implements Fooable {
    ...
}

然后FooSubClass

public class FooSubClass extends AbstractSubClass {
    ...
}

然后你的领域是:

private AbstractSubClass field1;

哪个会接受FooSubClass但不接受SubClass

它是编译器可以保证field1实际上具有所有必需方法的实现的唯一方法。


这是一个教科书示例来说明:

public class Bird() {
    public void eat() { 
        ....
    }
}

public interface FlyingBehaviour() {
    void fly();
}

public abstract class FlyingBird extends Bird implements FlyingBehaviour() {
    ...
}

public class Eagle extends FlyingBird {
    ...
}

public class Penguin extends Bird {
    ...
}

FlyingBird bird = new Eagle();
bird.fly();

FlyingBird bird = new Penguin(); //Compilation Error - Penguins cant fly!

答案 1 :(得分:1)

java中没有办法确保对象字段继承/实现两个不同的类。 假设您可以控制所有对象,最简单的方法是让您的基类实现Fooable。

答案 2 :(得分:0)

由于您使用assign方法设置字段,因此您可以使用该方法中的instanceof检查它是否是正确的对象类型。

public void assign(BaseClass baseClass) {
    if (baseClass instanceof foo)
       field3 = baseClass;
}

如果提供了未实现foo的类,则可能抛出异常。

编辑: Doh,没有看到修复应该是编译时。