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

Ine*_*ego 2 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
    }

}
Run Code Online (Sandbox Code Playgroud)

Java还允许将接口用作类型.如果我们有一个界面Fooable,

public interface Fooable {
    void foo();
}
Run Code Online (Sandbox Code Playgroud)

我们Example班可以有一个类型的领域Fooable,

    Fooable field2;
Run Code Online (Sandbox Code Playgroud)

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

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

public class FooSubClass extends BaseClass implements Fooable {
    @Override
    public void foo() {
        // TODO
    }
}
Run Code Online (Sandbox Code Playgroud)

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

cow*_*wls 8

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

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

public class abstract AbstractSubClass extends BaseClass implements Fooable {
    ...
}
Run Code Online (Sandbox Code Playgroud)

然后FooSubClass:

public class FooSubClass extends AbstractSubClass {
    ...
}
Run Code Online (Sandbox Code Playgroud)

然后你的领域是:

private AbstractSubClass field1;
Run Code Online (Sandbox Code Playgroud)

哪个会接受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!
Run Code Online (Sandbox Code Playgroud)

  • cowls已经回答了你的问题,但如果你确实想用泛型做这个,你可以做`<T extends BaseClass&Fooable>` (2认同)