Home > Enterprise >  Java implement class in interface
Java implement class in interface

Time:05-18

Say I have the following classes:

public abstract class Crop {
}

public abstract class Fruit extends Crop {
}

public interface Edible /* ALWAYS IMPLEMENTED BY A CROP */ {
}

public class Apple extends Fruit implements Edible /* BOTH A CROP AND EDIBLE */{
}

public class Holly extends Fruit /* NOT EDIBLE */ {
}

public class Wheat extends Crop implements Edible {
}

Now, I want to make sure that every Edible (interface) is a Crop (class).

Why can I not say:

public interface Edible implements Crop {
}

So that Edible itself can only be implemented by classes that extend Crop?

Is there a workaround for this, especially when passing Edible as a generic parameter that requires a Crop?

CodePudding user response:

You cannot implement a Java Class on an Interface. Interfaces can only extend other interfaces. So, in that way, you can declare other interface (and implemet it on Crop). Then, you can extend this new interface on Editable.

This can be something like:

public abstract class Crop implements NewInterface{
}

public interface Edible extends NewInterface {
}

CodePudding user response:

The only option to restrict what classes can implement an interface is using a sealed interface (introduced in Java 17), which restrict what class can inherit it. However, your use-case has the "problem" that not all crops are edible, which complicates matters.

On the face of it, your problem is not solvable, unless you want to explicitly list all possible classes in the interface.

For example, your problem could be solved like

public sealed interface Edible 
        permits Apple, Wheat {
}

public abstract class Crop {
}

public abstract class Fruit extends Crop {
}

public final class Apple extends Fruit implements Edible /* BOTH A CROP AND EDIBLE */{
}

public class Holly extends Fruit /* NOT EDIBLE */ {
}

public final class Wheat extends Crop implements Edible {
}

You could relax some of the constraints by using something like:

public sealed interface Edible 
        permits EdibleFruit, Wheat {
}

public abstract class Crop {
}

public abstract class Fruit extends Crop {
}

public non-sealed abstract class EdibleFruit extends Crop implements Edible {
}

public class Apple extends EdibleFruit /* BOTH A CROP AND EDIBLE */{
}

public class Holly extends Fruit /* NOT EDIBLE */ {
}

public final class Wheat extends Crop implements Edible {
}

But that could lead to a complicated hierarchy (e.g. consider that some sub-types of an edible fruit are not edible).

  • Related