devstory

Classe abstraite et interface dans C#

  1. Introduction
  2. La classe abstraite (Abstract Class)
  3. Exemples avec la classe abstraite
  4. La vue générale de l'Interface
  5. Structure d'une Interface
  6. La classe met en oeuvre Interface

1. Introduction

Dans ce document, je vais donner des instructions de l'interface et la classe abstraite (Abstract Class) en analysant les similitudes et les différences entre eux.
D'abord, vous devez créer un projet nommé AbstractClassInterface pour travailler avec des exemples.
On le désigne le projet par défaut.

2. La classe abstraite (Abstract Class)

Abstract class (La classe abstraite). Observez l'exemple de telle classe:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AbstractClassInterface
{
   // Une classe a au moins une méthode abstraite,
   // doit être déclarée comme abstraite (abstract).
   public abstract class ClassA
   {

       // C'est une méthode abstraite.
       // Il n'a pas de corps.
       // Le 'access modifier' de cette méthode est public
       // (access modifier: modificateur d'accès).
       public abstract void DoSomething();

       // 'access modifier' của phương thức này là: protected
       protected abstract String DoNothing();

      
       protected abstract void Todo();
   }

   // Đây là một class trừu tượng.
   // Nó được khai báo là trừu tượng, mặc dù nó không có phương thức trừu tượng nào.
   public abstract class ClassB
   {

   }
}
Des caractéristiques d'une classe abstraite sont:
  • Elle est déclarée avec le mot clé abstract.
  • Elle peut déclarer 0, 1 ou plusieurs de méthodes abstraites à l'intérieur.
  • vous ne pouvez pas initialiser un objet directement à partir une classe abstraite.

3. Exemples avec la classe abstraite

Observez l'illustration:
AbstractJob.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AbstractClassInterface
{
    // Une classe a au moins une méthode abstraite,
    // doit être déclarée comme abstraite (abstract).
    public abstract class AbstractJob
    {

        public AbstractJob()
        {

        }

        // C'est une méthode abstraite.
        // Il n'a pas de corps (body).
        // Cette méthode renvoie le nom du travail.
        public abstract String GetJobName();

        // C'est une méthode abstraite.
        // Il n'a pas de corps (body).
        public abstract void DoJob();

        // C'est une méthode normale (n'est pas la méthode abstraite).
        public void StopJob()
        {
            Console.WriteLine("Stop");
        }
    }
}
JavaCoding.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AbstractClassInterface
{
    public class JavaCoding : AbstractJob
    {

        public JavaCoding()
        {
        }

        // Implémente la méthode abstraite déclarée à la superclasse.
        // Il doit avoir un corps (body).
        // (Le mot-clé 'override' est requis.)
        public override void DoJob()
        {
            Console.WriteLine("Coding Java...");
        }

        // Implémente la méthode abstraite de la superclasse.
        public override String GetJobName()
        {
            return "Java Coding";
        }

        public void TestExample()
        {
            Console.WriteLine("Testing Example...");
        }
    }

}
CSharpCoding.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AbstractClassInterface
{
    class CSharpCoding : AbstractJob
    {
        public CSharpCoding()
        {
        }

        // Implémente la méthode abstraite de la superclasse.
        // Il n'a pas de corps (body).
        // (Le mot-clé 'override' est requis).
        public override void DoJob()
        {
            Console.WriteLine("Coding CSharp...");
        }

        // Implémente la méthode abstraite de la superclasse.
        public override String GetJobName()
        {
            return "CSharp Coding";
        }

        public void RunningExample()
        {
            Console.WriteLine("Running Example...");
        }
    }
}
ManualJob.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AbstractClassInterface
{

    // ManualJob - (Implémenteur des travaux manuels)
    // La classe mère (AbstractJob) a deux méthodes abstraites.
    // Cette classe implémente une méthode abstraite de la classe mère.
    // Par conséquent, il est obligatoire de déclarer 'abstract'.
    public abstract class ManualJob : AbstractJob
    {

        public ManualJob()
        {

        }

        // Implémente une méthode abstraite déclarée dans la classe mère.
        // (Le mot-clé 'override' est requis).
        public override String GetJobName()
        {
            return "Manual Job";
        }

    }
}
BuildHouse.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AbstractClassInterface
{

    // Cette classe est héritée de la classe ManualJob.
    // BuildHouse ne déclare pas 'abstract'
    // Il faut donc mettre en œuvre toutes les méthodes abstraites restantes.
    public class BuildHouse : ManualJob
    {

        public BuildHouse()
        {

        }

        // Cette méthode implémente la méthode abstraite déclarée dans la classe mère.
        // Cette méthode aura corps (corps).
        // (Nécessite un mot-clé 'override').
        public override void DoJob()
        {
            Console.WriteLine("Build a House");
        }

    }

}
Demo
JobDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AbstractClassInterface
{
    public class JobDemo
    {

        public static void Main(string[] args)
        {
            // Créer un objet AbstractJob via le constructeur de la classe JavaCoding.
            AbstractJob job1 = new JavaCoding();

            // Appeler la méthode DoJob().
            job1.DoJob();

            // La méthode GetJobName() est une classe abstraite dans la classe AbstractJob
            // Mais elle a été implémentée dans une certaines sous-classes.
            // Donc il est possible de l'appeler.
            String jobName = job1.GetJobName();

            Console.WriteLine("Job Name 1= " + jobName);


            // Créer un objet AbstractJob via le constructeur de la classe CSharpCoding.
            AbstractJob job2 = new CSharpCoding();

            // Appeler la méthode DoJob().
            job2.DoJob();

            String jobName2 = job2.GetJobName();

            Console.WriteLine("Job Name 2= " + jobName2);

            // Créer l'objet AbstractJob via le constructeur de la classe BuildHouse.
            AbstractJob job3 = new BuildHouse();

            job3.DoJob();

            String jobName3 = job3.GetJobName();

            Console.WriteLine("Job Name 3= " + jobName2);


            Console.ReadLine();
        }
    }

}
Exécution l'exemple:
Coding Java...
Job Name 1= Java Coding
Coding CSharp...
Job Name 2= CSharp Coding
Build a Hourse
Job Name 3= CSharp Coding

4. La vue générale de l'Interface

Nous savons qu'une classe ne peut qu'étendre une autre classe.
// La classe B est la sous-classe A ou B est étendue (extends) de A
// CSharp autorise uniquement la classe étendue à partir d'une seule autre classe.
public class B : A  
{
  // ....
}

// Au cas où vous ne spécifiez pas cette classe est héritée de quelle classe.
// CSharp comprend que cette classe s'étend de la classe Object.
public class B
{

}

// La façon de déclarer cette classe est similaire à la manière ci-dessus.
public class B : Object
{

}
Mais une classe peut étendre à partir de quelques Interfaces.
// Une classe s'étend d'une seule autre classe
// mais peut implémenter de nombreuses interfaces
public class Cat : Animal, CanEat, CanDrink
{

     // ....
}
Des caractéristiques de l' interface dans CSharp.
  • Interface possède des modificateurs publics ou internes, s'il ne précise pas, on le considère comme un modificateur interne par défaut.
  • Interface ne peut pas définir le champ (Field).
  • Ses méthodes sont abstraites (abstract) et publiques (public), et il n'y a pas le corps de fonction. Mais quand vous déclarez la méthode, vous n'êtes pas permis de préciser public ou abstract.
  • Interfacen'a pas de constructeur (Constructor).

5. Structure d'une Interface

Une interface dans CSharp peut déclarer des modificateurs étant public ou internal, si elle ne déclare pas, le modificateur est internal par défaut. Interface dispose un modificateur public qui peut être utilisé partout, alors que interface dispose un modificateur internal qui n'utilise qu'à l'intérieur (Assembly).
Un Assembly est le résultat compilé (compile) de votre code, généralement un DLL, mais EXE est également considéré comme un assembly. C'est l'unité la plus petite de déploiement n'importe quel projet .NET.

Assembly généralement comprens le code .NET dans MSIL (Microsoft Intermediate language - un langage intermédiaire) qui va être compilé au code indigène (Native code) ("JITted" - est compilé par le compilateur Just-In-Time) dans la première fois, il est exécuté sur la machine donnée. Ce code compilé va être stocké dans Assembly et réutiliser dans des appels subséquents.
NoAccessModifierInterface.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AbstractClassInterface
{

    // Ceci est une interface qui ne déclare pas 'access modifier'.
    // Par défaut, son 'access modifier' est 'internal'.
    // Il ne peut être utilisé que dans un Assembly.
     interface NoAccessModifierInterface
    {

    }

}
Des méthodes dans Interface sont publiques (public) et abstraites (abstract). Elles n'ont pas de corps, mais vous n' êtes pas autorisé d'écrire public ou abstract quand vous les déclarez.
CanMove.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AbstractClassInterface
{

    // Cette interface définit un standard sur des choses capables de bouger.
    public interface CanMove
    {

        // Les méthodes de l'interface sont publiques et abstraites (public abstract)
        // (Mais vous n'êtes pas autorisé à écrire 'public' ou 'abstract' ici).
        void Run();

        // Arrière.
        void Back();

        // Renvoyer de la vitesse.
        int GetVelocity();

    }

}
CanDrink.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AbstractClassInterface
{

    // Cette interface définit une chose sur les choses capables de boire.
    public interface CanDrink
    { 

          void Drink(); 

    }

}
CanEat.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AbstractClassInterface
{

    // Cette interface définit un standard sur des choses capables de manger.
    public interface CanEat
    {

          void Eat(); 
    }

}

6. La classe met en oeuvre Interface

Quand une classe met en oeuvre une Interface, vous devez mettre en oeuvre ou déclarer toutes les méthodes qui sont compris dans Interface.
  1. Si vous mettez en oeuvre certaines méthodes de l' interface, vous devez écrire le contenu de la méthode, déclarer la méthode étant publique.
  2. Si vous ne mettez pas en oeuvre certaines méthodes de l' interface, vous devez les déclarer dans la classe avec le mot- clé 'public abstract' et n'écrivez pas le contenu de méthode.
Observez l'exemple, la classe Animal met en oeuvre l'interface CanMove.
Animal.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AbstractClassInterface
{

    // Animal (Une classe décrit des animaux)
    // Cette classe s'étend de la classe Object. (Malgré que ce n'est pas évident).
    // Et implémente (implements) l'interface CanMove.
    // Interface CanMove a 3 méthodes abstraites.
    // Cette classe implémente une seule méthode abstraite de CanMove.
    // Par conséquent, elle doit être déclarée 'abstract'.
    // Les méthodes restantes doivent être déclarées avec 'public abstract'.
    public abstract class Animal : CanMove
    {

        // Implémentez la méthode Run() de l'interface CanMove.
        // Vous devez écrire le contenu de la méthode.
        // Le modificateur d'accès doit être public.
        public void Run()
        {
            Console.WriteLine("Animal run...");
        }

        // Si cette classe n'implémente pas une certaine méthode d'interface
        // vous devez le réécrire en tant que méthode abstraite.
        // (Toujours est 'public abstract')
        public abstract void Back(); 

        public abstract int GetVelocity();

    }


}
La classe Cat hérite de la classe Animal en mettant en oeuvre 2 interfaces CanDrink, CanEat.
Cat.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AbstractClassInterface
{

    // La classe Cat s'étend de la classe Animal et implémente l'interface CanEat, CanDrink.
    public class Cat : Animal, CanEat, CanDrink
    {

        private String name;

        public Cat(String name)
        {
            this.name = name;
        }

        public String getName()
        {
            return this.name;
        }

        // Implémente la méthode abstraite Animal.
        // (il faut préciser 'override' ).
        public override void Back()
        {
            Console.WriteLine(name + " cat back ...");
        }

        // Implémente la méthode abstraite d'Animal.
        // (Il doit préciser 'override' )
        public override int GetVelocity()
        {
            return 110;
        }

        // Implémente la méthode abstraite de l'interface CanEat.
        public void Eat()
        {
            Console.WriteLine(name + " cat eat ...");
        }

        // Implémente la méthode abstraite de l'interface CanDrink
        public void Drink()
        {
            Console.WriteLine(name + " cat drink ...");
        }

    }

}
Mouse.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AbstractClassInterface
{
    public class Mouse : Animal, CanEat, CanDrink
    {

        // Implémente la méthode abstraite de la classe Animal.
        // (INécessite d'avoir le mot-clé 'override').
        public override void Back()
        {
            Console.WriteLine("Mouse back ...");
        }

        // Implémente la méthode abstraite de la classe Animal.
        public override int GetVelocity()
        {
            return 85;
        }

        // Implémente la méthode abstraite de l'interface CanDrink.
        public void Drink()
        {
            Console.WriteLine("Mouse drink ...");
        }

        // Implémente la méthode abstraite de l'interface CanEat.
        public void Eat()
        {
            Console.WriteLine("Mouse eat ...");
        }

    }

}
AnimalDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AbstractClassInterface
{

    public class AnimalDemo
    {

        public static void Main(string[] args)
        {

            // Créer un objet CanEat.
            // Un objet déclaré comme CanEat
            // En fait, c'est Cat (le chat).
            CanEat canEat1 = new Cat("Tom");

            // Un objet déclaré comme CanEat
            // En fait, c'est la souris (Mouse).
            CanEat canEat2 = new Mouse();

            // Le polymorphisme (Polymorphism) est montré ici.
            // CSharp connaît le type réel d'un objet.
            // ==> Tom cat eat ...
            canEat1.Eat();

            // ==> Mouse eat ...
            canEat2.Eat();

            bool isCat = canEat1 is Cat;// true

            Console.WriteLine("catEat1 is Cat? " + isCat);

            // Vérifiez si 'canEat2' est la souris ou non?.
            if (canEat2 is Mouse)
            {
                // Cast
                Mouse mouse = (Mouse)canEat2;

                // Appeler la méthode Drink() (héritée de CanDrink).
                mouse.Drink();
            }

            Console.ReadLine();
        }
    }

}
Exécution l'exemple:
Tom cat eat ...
Mouse eat ...
catEat1 is Cat? True
Mouse drink ...