• Aucun résultat trouvé

Une classe abstraite est une classe particulière qui ne peut pas être instanciée. Concrètement, cela veut dire que nous ne pourrons pas utiliser l’opérateur new.

De la même façon, une méthode abstraite est une méthode qui ne contient pas d’implémentation, c’est-à-dire pas de code. Pour être utilisables, les classes abstraites doivent être héritées et les méthodes redéfinies.

En général, les classes abstraites sont utilisées comme classe de base pour d’autres classes. Ces classes fournissent des comportements mais n’ont pas vraiment d’utilité à avoir une vie propre. Ainsi, les classes filles qui en héritent pourront bénéficier de leurs comportements et devront éventuellement en remplacer d’autres.

C’est comme une classe incomplète qui ne demande qu’à être complétée.

Si une classe possède une méthode abstraite, alors la classe doit absolument être abstraite. L’inverse n’est pas vrai, une classe abstraite peut posséder des méthodes non abstraites.

Vous aurez rarement besoin d’utiliser les classes abstraites en tant que débutant mais elles pourront vous servir pour combiner la puissance des interfaces à l’héritage.

Bon, voilà pour la théorie, passons un peu à la pratique.

Rappelez-vous nos chiens et nos chats qui dérivent d’une classe mère Animal. Nous savons qu’un Animal est capable de se déplacer. C’est un comportement qu’ont en commun tous les animaux. Il est tout à fait logique de définir une méthode

SeDeplacer() au niveau de la classe Animal. Sauf qu’un chien ne se déplace pas forcément comme un dauphin. L’un a des pattes, l’autre des nageoires. Et même si le chien et le chat semblent avoir un déplacement relativement proche, ils ont chacun des subtilités. Le chat a un mouvement plus gracieux, plus félin.

Bref, on se rend compte que nous sommes obligés de redéfinir la méthode SeDeplacer() dans chaque classe fille de la classe Animal. Et puis de toute façon, sommes-nous vraiment capables de dire comment se déplace un animal dans l’absolu ?

possède pas d’implémentation et chaque classe fille de la classe possédant cette méthode abstraite devra la spécialiser. C’est exactement ce qu’il nous faut.

Pour déclarer une méthode comme étant abstraite, il faut utiliser le mot-clé abstract et ne fournir aucune implémentation de la méthode, c'est-à-dire que la déclaration de la méthode doit se terminer par un point-virgule :

Code : C#

public class Animal {

public abstract void SeDeplacer(); }

Si nous tentons de compiler cette classe, nous aurons l’erreur suivante : Code : Console

'MaPremiereApplication.Animal.SeDeplacer()' est abstrait, mais est contenu dans la classe non abstraite 'MaPremiereApplication.Animal'

Ah oui c’est vrai, on a dit qu’une classe qui contient au moins une méthode abstraite était forcément abstraite. C’est le même principe que pour la méthode, il suffit d’utiliser le mot-clé abstract devant le mot-clé class :

Code : C#

public abstract class Animal {

public abstract void SeDeplacer(); }

Voilà, notre classe peut compiler tranquillement.

Nous avons également dit qu’une classe abstraite pouvait contenir des méthodes concrètes et que c’était d’ailleurs une des grandes forces de ce genre de classes. En effet, il est tout à fait pertinent que des animaux puissent mourir. Et là, ça se passe pour tout le monde de la même façon, le cœur arrête de battre et on ne peut plus rien faire. C’est triste, mais c’est ainsi.

Cela veut dire que nous pouvons créer une méthode Mourir() dans notre classe abstraite qui possède une implémentation. Cela donne :

Code : C#

public abstract class Animal {

private Coeur coeur; public Animal() {

coeur = new Coeur(); }

public abstract void SeDeplacer(); public void Mourir()

{

coeur.Stop(); }

Avec une classe Cœur qui ne fait pas grand-chose : Code : C#

public class Coeur {

public void Battre() {

Console.WriteLine("Boom boom"); }

public void Stop() {

Console.WriteLine("Mon coeur s'arrête de battre"); }

}

Comme prévu, il n’est pas possible d’instancier un objet Animal. Si nous tentons l’opération : Code : C#

Animal animal = new Animal();

nous aurons l’erreur de compilation suivante : Code : Console

Impossible de créer une instance de la classe abstraite ou de l'interface 'MaPremiereApplication.Animal'

Par contre, il est possible de créer une classe Chien qui dérive de la classe Animal : Code : C#

public class Chien : Animal {

}

Cette classe ne pourra pas compiler dans cet état car il faut obligatoirement redéfinir la méthode abstraite SeDeplacer(). Cela se fait en utilisant le mot-clé override, comme on l’a déjà vu.

Vous aurez sûrement remarqué que la méthode abstraite n’utilise pas le mot-clé virtual comme cela doit absolument être le cas lors de la substitution d’une méthode dans une classe non-abstraite. Il est ici implicite et ne doit pas être utilisé, sinon nous aurons une erreur de compilation. Et puis cela nous arrange, un seul mot-clé, c’est largement suffisant !

Nous devons donc spécialiser la méthode SeDeplacer, soit en écrivant la méthode à la main, soit en utilisant encore une fois notre ami Visual C# Express.

Il suffit de faire un clic droit sur la classe dont hérite Chien (en l’occurrence Animal) et de cliquer sur « Implémenter une classe abstraite » :

Visual C# Express nous génère donc la signature de la méthode à substituer : Code : C#

public class Chien : Animal {

public override void SeDeplacer() {

throw new NotImplementedException(); }

}

Il ne reste plus qu’à écrire le corps de la méthode SeDeplacer, par exemple : Code : C#

public class Chien : Animal {

public override void SeDeplacer() {

Console.WriteLine("Waouf ! Je me déplace avec mes 4 pattes");

} }

Ainsi, nous pourrons créer un objet Chien et le faire se déplacer puis le faire mourir car il hérite des comportements de la classe Animal. Paix à son âme.

Code : C#

Chien max = new Chien(); max.SeDeplacer();

max.Mourir();