An interface is a particular abstract data type that may define abstract methods and variables. Any concrete class implementing the interface will inherit these methods/variables and must implement each non default method.
An interface is created with this modifiers
package nature; public abstract interface Herbivore { public default boolean isVegetarian(){return true;} public boolean isPoisonous() ; public default void setLegs(int legs) throws IllegalArgumentException { if (legs < 1) throw new IllegalArgumentException("One Leg??"); System.out.println(legs); }; }
Interestingly one can create only public
or package-private interfaces!
Interface variables are only public static final
variables and must be initialized at declaration.
The visibility of Interface methods can only be public
or package-private. Methods are supposed to be abstract
and not to provide an implementation. However, one may provide an implementation marking the method as default
.
One may also define static
methods with implementation that are helper methods for the interface.
Because of polymorphism when implementing the methods of an interface in a concrete class there are a number of restrictions:
package pond; import nature.*; public class GoldFish extends Fish implements Herbivore{ private String my_name; public GoldFish(String my_name){ this.my_name = my_name; this.commonName = "Gold Fish"; this.livesInFreshWater = true; } public GoldFish() { this("Goldie"); } public String getName(){ return my_name; } public boolean isPoisonous(){return false;} public void setLegs(int legs) throws NegativeLegsException { if (legs < 0) throw new NegativeLegsException("Negative legs"); System.out.println(legs); } } class NegativeLegsException extends IllegalArgumentException { public NegativeLegsException(String e){ super(e); } }
In the example above the Herbivore
interface throws
an IllegalArgumentException
on the default
method setLegs()
.
Because one may treat the GoldFish
like an Herbivore
it may be that we don't know anything about the particular exception NegativeLegsException
but we are aware that Herbivore throws IllegalArgumentException
and we can handle that.
In a try/catch we can catch an exception with its superclass, but we cannot do the opposite.
That is why, overriding the method that throws and exception, if we were allowed to change the exception to a superclass or to another type of checked exception, there could be the chance that we do not declare or catch the checked exception, and we cannot do that!
Overriding a method or a variable cannot be done as we wish because of polymorphism. Our interface Herbivore defines an abstract method
public boolean isPoisonous();
The method is public abstract
and the last concrete class implementing it must provide an implementation.
As a matter of facts GoldFish
overrides it with a method
public boolean isPoisonous(){ return false; }
Let's see what would happen if GoldFish would have provided another implementation, or similar but with a different accessibility modifier
boolean isPoisonous(){ return false; }
This would give problems when we would try to extend the GoldFish
class from another package, because now the implementation is package-private, therefore unavailable to other packages!
package acquarium; import pond.*; import nature.*; public class Acquarium { public static void main(String... args){ Herbivore goldie = new GoldFish("Poppy"); // can you touch goldie? is it poisonous? if (!goldie.isPoisonous()) { touch(); } } public static void touch(){ System.out.println("Can touch"); } }
Because we are now treating Goldie as an Herbivore we are confident to be able to check if it is poisonous or not via the isPoisonous()
method of the interface. But since GoldFish
has implemented the method and changed the access modifier to something more restrictive (package private), we cannot access the method from a different package and we are in trouble!
We may die because the little Goldie may be poisonous. Java prevents this by not letting us compile!
pond/GoldFish.java:18: error: isPoisonous() in GoldFish cannot implement isPoisonous() in Herbivore boolean isPoisonous(){return false;} ^ attempting to assign weaker access privileges; was public 1 error