Inego
Inego

Reputation: 1159

Restricting a field to be an instance of a class AND implementing an interface at the same time

Java allows to assign subclass instances to class-typed fields, for example:

public class BaseClass {

}

public class SubClass extends BaseClass {

}

public class Example {

    private BaseClass field1;

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

}

Java allows also to use interfaces as types. If we have an interface Fooable,

public interface Fooable {
    void foo();
}

our Example class can have a field of type Fooable,

    Fooable field2;

That is, it is possible to assign to field2 an instance of any class implementing Fooable interface.

But what if I want to tell the compiler that field3 has to be both an instance of BaseClass and implementation of Fooable interface? So that, if there is a class

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

, I could assign to field3 instances of FooSubClass but not of SubClass? Is it possible without using generics of any sort?

Upvotes: 2

Views: 90

Answers (3)

cowls
cowls

Reputation: 24334

You can't do it like you are trying to.

You would need to define another class, perhaps an abstract class would suit you here:

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

Then FooSubClass:

public class FooSubClass extends AbstractSubClass {
    ...
}

Then your field is:

private AbstractSubClass field1;

Which will accept FooSubClass but not SubClass

Its the only way the compiler can guarantee that field1 will actually have implementations of all the required methods.


Here is a textbook example to illustrate:

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!

Upvotes: 8

Deadron
Deadron

Reputation: 5289

There is no way in java to ensure a object field inherits/implements two different classes. Assuming you have control of all the objects here, the easiest fix would be for your base class to implement Fooable.

Upvotes: 1

ghdalum
ghdalum

Reputation: 891

Since you are using a assign-method for setting the fields, you can check if it is correct type of object using instanceof in that method.

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

You may throw an exception if class not implementing foo is provided.

edit: Doh, didn't see that the fix should be for compile-time.

Upvotes: 0

Related Questions