Java Language Classe abstraite et utilisation de l'interface: relation "Is-a" vs capacité "Has-a"


Exemple

Quand utiliser des classes abstraites: Pour implémenter le même comportement ou un comportement différent parmi plusieurs objets associés

Quand utiliser les interfaces: pour implémenter un contrat par plusieurs objets non liés

Les classes abstraites create "is a" relations alors que les interfaces fournissent "a une" capacité.

Cela peut être vu dans le code ci-dessous:

public class InterfaceAndAbstractClassDemo{
    public static void main(String args[]){
        
        Dog dog = new Dog("Jack",16);
        Cat cat = new Cat("Joe",20);
            
        System.out.println("Dog:"+dog);
        System.out.println("Cat:"+cat);
        
        dog.remember();
        dog.protectOwner();
        Learn dl = dog;
        dl.learn();
                
        cat.remember();
        cat.protectOwner();
        
        Climb c = cat;
        c.climb();
        
        Man man = new Man("Ravindra",40);
        System.out.println(man);
        
        Climb cm = man;
        cm.climb();
        Think t = man;
        t.think();
        Learn l = man;
        l.learn();
        Apply a = man;
        a.apply();
    }
}

abstract class Animal{
    String name;
    int lifeExpentency;
    public Animal(String name,int lifeExpentency ){
        this.name = name;
        this.lifeExpentency=lifeExpentency;
    }
    public abstract void remember();
    public abstract void protectOwner();
    
    public String toString(){
        return this.getClass().getSimpleName()+":"+name+":"+lifeExpentency;
    }
}
class Dog extends Animal implements Learn{
    
    public Dog(String name,int age){
        super(name,age);
    }
    public void remember(){
        System.out.println(this.getClass().getSimpleName()+" can remember for 5 minutes");
    }
    public void protectOwner(){
        System.out.println(this.getClass().getSimpleName()+ " will protect owner");
    }
    public void learn(){
        System.out.println(this.getClass().getSimpleName()+ " can learn:");
    }
}
class Cat extends Animal implements Climb {
    public Cat(String name,int age){
        super(name,age);
    }
    public void remember(){
        System.out.println(this.getClass().getSimpleName() + " can remember for 16 hours");
    }
    public void protectOwner(){
        System.out.println(this.getClass().getSimpleName()+ " won't protect owner");
    }
    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 Man implements Think,Learn,Apply,Climb{
    String name;
    int age;

    public Man(String name,int age){
        this.name = name;
        this.age = age;
    }
    public void think(){
        System.out.println("I can think:"+this.getClass().getSimpleName());
    }
    public void learn(){
        System.out.println("I can learn:"+this.getClass().getSimpleName());
    }
    public void apply(){
        System.out.println("I can apply:"+this.getClass().getSimpleName());
    }
    public void climb(){
        System.out.println("I can climb:"+this.getClass().getSimpleName());
    }
    public String toString(){
        return "Man :"+name+":Age:"+age;
    }
}

sortie:

Dog:Dog:Jack:16
Cat:Cat:Joe:20
Dog can remember for 5 minutes
Dog will protect owner
Dog can learn:
Cat can remember for 16 hours
Cat won't protect owner
Cat can climb
Man :Ravindra:Age:40
I can climb:Man
I can think:Man
I can learn:Man
I can apply:Man

Notes clés:

  1. Animal est une classe abstraite avec des attributs partagés: name et lifeExpectancy et des méthodes abstraites: remember() et protectOwner() . Dog and Cat sont des Animals qui ont implémenté les méthodes remember() et protectOwner() .

  2. Cat peut climb() mais Dog ne peut pas. Dog peut think() mais Cat ne peut pas. Ces fonctionnalités spécifiques sont ajoutées à Cat et Dog par implémentation.

  3. Man n'est pas un Animal mais il peut Think , Learn , Apply et Climb .

  4. Cat n'est pas un Man mais il peut Climb .

  5. Dog n'est pas un Man mais il peut Learn

  6. Man n'est ni un Cat ni un Dog mais peut avoir certaines des capacités de ces deux derniers sans étendre Animal , Cat ou Dog . Ceci est fait avec des interfaces.

  7. Même si Animal est une classe abstraite, il a un constructeur, contrairement à une interface.

TL; DR:

Les classes non liées peuvent avoir des capacités via des interfaces, mais les classes associées modifient le comportement via l'extension des classes de base.

Reportez-vous à la page de documentation Java pour savoir laquelle utiliser dans un cas d'utilisation spécifique.

Envisagez d'utiliser des classes abstraites si ...

  1. Vous voulez partager du code entre plusieurs classes étroitement liées.
  2. Vous vous attendez à ce que les classes qui étendent votre classe abstraite disposent de nombreuses méthodes ou champs communs, ou requièrent des modificateurs d'accès autres que publics (tels que protégés et privés).
  3. Vous souhaitez déclarer des champs non statiques ou non finaux.

Envisagez d'utiliser des interfaces si ...

  1. Vous vous attendez à ce que des classes non liées implémentent votre interface. Par exemple, de nombreux objets non liés peuvent implémenter l'interface Serializable .
  2. Vous voulez spécifier le comportement d'un type de données particulier mais ne vous préoccupez pas de savoir qui implémente son comportement.
  3. Vous voulez profiter de l'héritage multiple de type.