When to use abstract classes: To implement the same or different behaviour among multiple related objects
When to use interfaces: to implement a contract by multiple unrelated objects
Abstract classes create "is a" relations while interfaces provide "has a" capability.
This can be seen in the code below:
public class DemoApp { public static void main(String[] args) { MyDog myDog = new MyDog("Buddy", 3); MyCat myCat = new MyCat("Whiskers", 5); System.out.println("MyDog: " + myDog); System.out.println("MyCat: " + myCat); myDog.remember(); myDog.protectOwner(); Learn learningDog = myDog; learningDog.learn(); myCat.remember(); myCat.protectOwner(); Climb climbingCat = myCat; climbingCat.climb(); Human human = new Human("John", 30); System.out.println(human); Climb climbingHuman = human; climbingHuman.climb(); Think thinkingHuman = human; thinkingHuman.think(); Learn learningHuman = human; learningHuman.learn(); Apply applyingHuman = human; applyingHuman.apply(); } } abstract class MyAnimal { String name; int lifeExpectancy; public MyAnimal(String name, int lifeExpectancy) { this.name = name; this.lifeExpectancy = lifeExpectancy; } public abstract void remember(); public abstract void protectOwner(); @Override public String toString() { return this.getClass().getSimpleName() + ":" + name + ":" + lifeExpectancy; } } class MyDog extends MyAnimal implements Learn { public MyDog(String name, int age) { super(name, age); } @Override public void remember() { System.out.println(this.getClass().getSimpleName() + " can remember for 5 minutes"); } @Override public void protectOwner() { System.out.println(this.getClass().getSimpleName() + " will protect owner"); } @Override public void learn() { System.out.println(this.getClass().getSimpleName() + " can learn"); } } class MyCat extends MyAnimal implements Climb { public MyCat(String name, int age) { super(name, age); } @Override public void remember() { System.out.println(this.getClass().getSimpleName() + " can remember for 16 hours"); } @Override public void protectOwner() { System.out.println(this.getClass().getSimpleName() + " won't protect owner"); } @Override public void climb() { System.out.println(this.getClass().getSimpleName() + " can climb"); } } interface Climb { void climb(); } interface Think { void think(); } interface Learn { void learn(); } interface Apply { void apply(); } class Human implements Think, Learn, Apply, Climb { String name; int age; public Human(String name, int age) { this.name = name; this.age = age; } @Override public void think() { System.out.println("I can think: " + this.getClass().getSimpleName()); } @Override public void learn() { System.out.println("I can learn: " + this.getClass().getSimpleName()); } @Override public void apply() { System.out.println("I can apply: " + this.getClass().getSimpleName()); } @Override public void climb() { System.out.println("I can climb: " + this.getClass().getSimpleName()); } @Override public String toString() { return "Human: " + name + ":Age:" + age; } }
Output:
MyDog: MyDog:Buddy:3 MyCat: MyCat:Whiskers:5 MyDog can remember for 5 minutes MyDog will protect owner MyDog can learn MyCat can remember for 16 hours MyCat won't protect owner MyCat can climb Human: John:Age:30 Human can climb: Human Human can think: Human Human can learn: Human Human can apply: Human
Consider using abstract classes if...
Consider using interfaces if...
Static method can be inherited similar to normal methods, however unlike normal methods it is impossible to create "abstract" methods in order to force static method overriding. Writing a method with the same signature as a static method in a super class appears to be a form of overriding, but really this simply creates a new function hides the other.
public class ParentClass { public static int number = 10; public static void greet() { System.out.println("Greetings"); } public static void main(String[] args) { ParentClass.greet(); System.out.println("ParentClass's number: " + ParentClass.number); ChildClass.greet(); // This will be different than the above statement's output since it runs // a different method ChildClass.greet(true); StaticOverride.greet(); System.out.println("StaticOverride's number: " + StaticOverride.number); } } public class ChildClass extends ParentClass { // Inherits the greet function but does not override it public static void greet(boolean test) { System.out.println("Hey there"); } } public static class StaticOverride extends ParentClass { // Hides the number field from ParentClass // You can even change the type, as this doesn't affect the signature public static String number = "modified"; // Cannot use @Override annotation since this is static // This overrides the greet method from ParentClass public static void greet() { System.out.println("Static says Hi"); } }
Running any of these classes produces the output:
Greetings ParentClass's number: 10 Greetings Hey there Static says Hi StaticOverride's number: modified
Note that unlike normal inheritance, in static inheritance methods are not hidden. You can always call the base sayHello method by using BaseClass.sayHello(). But classes do inherit static methods if no methods with the same signature are found in the subclass. If two method's signatures vary, both methods can be run from the subclass, even if the name is the same.
Learn All in Tamil © Designed & Developed By Tutor Joes | Privacy Policy | Terms & Conditions