• Aucun résultat trouvé

IFT 1179 : Programmation en C#

N/A
N/A
Protected

Academic year: 2022

Partager "IFT 1179 : Programmation en C#"

Copied!
17
0
0

Texte intégral

(1)

IFT 1179 : Programmation en C#

A) Suite de l’ENCAPSULATION :

1) Champs d’informations

(ou attributs ou membres de données)

: a) variables d’instance : des champs d’informations d’un objet de la classe :

- le rayon d’un objet de la classe Cercle

- les champs longueur, largeur d’un objet de la classe Rectangle

Pour chaque objet instancié (construit), le C# réserve l’espace de mémoire pour mémoriser ces champs et l’objet réfère vers cet espace réservée :

Rectangle r = new Rectangle (6.3, 5.2) ;

r

b) informations de la classe (champ static) : un champ déclaré avec la clause static. Il est alloué au même emplacement pour tous les objets de cette classe et il n’est pas associé à chaque objet mais plutôt à l’ensemble de tous les objets :

private static int nbRect = 0;

Le nombre total de rectangles instanciés est une

information de la classe, pas à chacun des rectangles.

6.3 5.2

(2)

Notez qu’un champ déclaré constant (clause const) est

toujours considéré comme static : Math.PI, int.MaxValue, … 2) Constructeurs :

Une classe peut disposer d’aucune, une ou de plusieurs constructeurs. Le but d’un constructeur est de construire (d’instancier) un objet d’une classe en donnant les valeurs aux champs d’information de la classe.

Comme on construit un objet en dehors de sa classe, c’est très une méthode public. Un constructeur n’est pas de type void ni return. C’est une méthode qui porte le même nom de la classe. Si la classe ne dispose aucun constructeur, C#

fournit un constructeur sans paramètre avec les valeurs par défaut (constructeur par défaut) pour les champs

d’informations.

using System;

class Aucun // constructeur { private int x;

private double y;

public void Afficher() {

Console.WriteLine("Dans la classe Aucun (constructeur) " + " x = {0} et y = {1}", x, y);

} }

class Constructeurs {

static void Main(string[] args) {

Aucun obj = new Aucun();

obj.Afficher();

} }

Exécution :

Dans la classe Aucun (constructeur) x = 0 et y = 0

(3)

Press any key to continue

Par contre, si une classe dispose déjà de constructeur(s), C# ne fournit plus de constructeur par défaut :

using System;

class Avec // constructeur {

private int x;

private double y;

public Avec(int a, double b) { x = a; y = b;

}

public void Afficher() {

Console.WriteLine("Dans la classe Avec (constructeur) " +

" x = {0} et y = {1}", x, y);

} }

class Constructeurs {

static void Main(string[] args) {

Avec obj = new Avec(5, 6.7);

obj.Afficher();

} }

Exécution :

Dans la classe Avec (constructeur) x = 5 et y = 6,7 Press any key to continue

Tandis que :

obj = new Avec();

provoque l’erreur :

«Aucune surcharge pour la méthode 'Avec' ne prend

d'arguments '0'»

(4)

La plupart des enseignants, auteurs des livres en POO nous suggèrent d’écrire un constructeur sans paramètre (avec un corps vide ou un contenu approprié).

Comme tous les constructeurs portent le même nom de la classe, c’est la surcharge des méthodes qui est utilisée.

Cas spécial : constructeur static

Ce genre de constructeur, assez rare, a pour but

d’initialiser les champs statics. On ne peut pas l’appeler explicitement. Il est convoqué avant l’instanciation même du premier objet de la classe.

using System;

class Employe {

private double salDeBase, // salaire de base bonus; // bonus personnel public const double BONUS_POUR_TOUS = 150;

private static int nbEmp ; // combien d'employes au total private static double somSal ; // somme des salaires

public Employe(double salaire, double b) {

salDeBase = salaire;

bonus = b;

nbEmp++;

somSal += Salaire();

}

private double Salaire() {

return salDeBase + bonus + BONUS_POUR_TOUS;

}

public Employe(double nbHeure, double taux, double b) {

salDeBase = nbHeure * taux;

bonus = b;

nbEmp++;

somSal += Salaire();

}

public Employe() {

}

(5)

static Employe() {

somSal = nbEmp = 0; // initialiser les champs statics

Console.WriteLine("Cet affichage est d'ordre pedagogique : "

+ " appel du constructeur static");

}

public void Afficher(string mess) {

Console.WriteLine("Pour l'employe " + mess + ":");

Console.WriteLine(" - salaire de base : {0, 6:F2} $", salDeBase);

Console.WriteLine(" - bonus personnel : {0, 6:F2} $", bonus);

Console.WriteLine(" - bonus du groupe : {0, 6:F2} $", BONUS_POUR_TOUS);

Console.WriteLine(" - salaire total : {0, 6:F2} $", Salaire());

Console.WriteLine();

}

public static void Afficher() {

Console.WriteLine("Au total : ");

Console.WriteLine(" - {0} employes", nbEmp);

Console.WriteLine(" - salaire moyen : {0, 6:F2}$", somSal /nbEmp);

} }

class Statics {

static void Main(string[] args) {

Console.WriteLine("Pour le groupe, le bonus pour tout" + " le monde : " + Employe.BONUS_POUR_TOUS);

Employe emp1 = new Employe(1000.00, 75.00);

emp1.Afficher("numero 1");

Employe emp2 = new Employe(52.50, 40.00, 300.75);

emp2.Afficher("employe #2");

Employe.Afficher();

} }

/* Exécution:

Pour le groupe, le bonus pour tout le monde : 150

Cet affichage est d'ordre pedagogique : appel du constructeur static Pour l'employe numero 1:

- salaire de base : 1000,00 $

(6)

- bonus personnel : 75,00 $ - bonus du groupe : 150,00 $ - salaire total : 1225,00 $ Pour l'employe employe #2:

- salaire de base : 2100,00 $ - bonus personnel : 300,75 $ - bonus du groupe : 150,00 $ - salaire total : 2550,75 $ Au total :

- 2 employes

- salaire moyen : 1887,88$

Press any key to continue

*/

3) Auto référence : this

En programmation orientée objet, l’objet courant est celui qu’on est en train de construire ou d’appliquer une méthode sur lui. Comme Java, en C# le mot clé this désigne l’objet courant (en C++, c’est un pointeur vers l’objet courant).

On utilise ce mot clé à l’intérieur d’une classe lorsque : a) il y a du conflit entre le nom d’un champ

d’information et le nom d’un paramètre public Cercle (double rayon) {

this.rayon = rayon;

}

le rayon du cercle courant le paramètre

(7)

b) on retourne l’objet courant dans une méthode :

/* cette méthode permet de déterminer et de retourner le cercle ayant le rayon le plus grand entre le cercle courant et un autre cercle */

public Cercle plusGrand (Cercle autre)

{ // si le rayon de l’autre cercle dépasse celui du // cercle courant

if ( autre.rayon > rayon ) return autre;

else

return this; // on retourne le cercle courant }

c) on veut clarifier l’infotrmation malgré que ce n’est pas une obligation :

if ( autre.rayon > this.rayon )

4) Méthodes d’accès et de modification (get, set) : Supposons qu’on dispose de la classe Cercle et dans la classe TestCercle on instancie le cercle suivant :

Cercle c = new Cercle (5.6);

Comment peut-on afficher seulement le rayon de ce cercle ?

(8)

L’instruction :

Console.WriteLine("Le rayon du cercle c : " + c.rayon) ;

est invalide car le champ rayon a été déclaré privé.

Un moyen pour le faire est d’ajouter une méthode public à la classe Cercle :

public void AfficherRayon() {

Console.WriteLine("Le rayon : " + rayon );

}

puis, dans TestCercle, on appelle cette méthode : c.AfficherRayon();

Cette manière est fonctionnelle mais rarement utilisée.

Les langages POO proposent de méthode d’accès en utilisant le verbe get (du sens : obtenir, accéder) :

Dans la classe Cercle, on écrit la méthode d’accès : public double GetRayon() {

return rayon;

}

Dans TestCercle, il suffit de l’appeler :

Console.WriteLine("Le rayon du cercle c : " + c.GetRayon()) ;

Maintenant, comment peut-on ajouter 0.4 au rayon de ce cercle ?

L’instruction : c.rayon += 0.4; est invalide car le champ

rayon est privé.

(9)

On peut procéder par une solution possible : Dans Cercle, on écrit :

public void Ajouter( double quantite) { rayon += quantite;

}

Dans TestCercle, on l’appelle : c.Ajouter(0.4);

Cette méthode fonctionne mais répond uniquement au besoin d’ajouter. Si on veut doubler le rayon, soustraire le rayon de 1.7, diviser le rayon par 3, on devrait écrire autres méthodes.

La plupart des langages POO proposent d’écrire de méthode de modification en utilisant le verbe en anglais set (du sens modifier, changer) :

Dans Cercle, on écrit :

public void SetRayon( double nouRayon ) rayon = nouRayon;

}

Dans TestCercle :

- pour doubler le rayon, on écrit : c.SetRayon ( 2 * c.GetRayon() );

- pour ajouter 0.4 au rayon, on écrit c.SetRayon ( c.GetRayon() + 0.4 );

- etc ...

(10)

/** Fichier GetSet.cs */

using System;

class Cercle {

private double rayon; // le rayon du cercle // un constructeur : à partir du rayon r donné public Cercle(double rayon) {

this.rayon = rayon;

}

// un autre constructeur : rayon par défaut vaur 4.5 public Cercle() {

rayon = 4.5; // par défaut, le rayon est 4.5 }

// méthode pour calculer, retourner le périmètre public double Perimetre() {

return 2 * Math.PI * rayon;

}

// méthode pour calculer, retourner la surface public double Surface() {

return Math.PI * rayon * rayon;

}

// méthode pour afficher les informations d'un cercle public void Afficher(string message) {

Console.WriteLine("Informations du cercle " + message + " : ");

Console.WriteLine("rayon : {0, 6:F2} ", rayon);

Console.WriteLine("perimetre : {0, 6:F2}", Perimetre());

Console.WriteLine("surface : {0, 6:F2}", + Surface());

Console.WriteLine();

}

// méthode d'accès

public double GetRayon() { return rayon;

}

// méthode de modification

public void SetRayon(double nouvRayon) {

rayon = nouvRayon;

}

public Cercle PlusGrand(Cercle autre) {

return rayon > autre.rayon ? this:autre;

} }

(11)

public class GetSet {

static void Main (string[] args) {

Cercle c1 = new Cercle(2.4);

c1.Afficher("c1");

Cercle c2 = new Cercle();

c2.Afficher("c2 avec rayon par defaut");

c1.PlusGrand(c2).Afficher("ayant le rayon le plus grand"

+ " parmi c1 et c2");

Console.WriteLine("Le rayon du cercle c1 presentement : " + c1.GetRayon());

c1.SetRayon ( 2 * c1.GetRayon());

Console.WriteLine("Le rayon du cercle c1 apres avoir double : "

+ c1.GetRayon());

c1.Afficher("c1 apres avoir double son rayon");

c1.PlusGrand(c2).Afficher("ayant le rayon le plus grand"

+ " parmi c1 et c2");

} }

/* Exécution:

Informations du cercle c1 : rayon : 2,40

perimetre : 15,08 surface : 18,10

Informations du cercle c2 avec rayon par defaut : rayon : 4,50

perimetre : 28,27 surface : 63,62

Informations du cercle ayant le rayon le plus grand parmi c1 et c2 : rayon : 4,50

perimetre : 28,27 surface : 63,62

Le rayon du cercle c1 presentement : 2,4

Le rayon du cercle c1 apres avoir double : 4,8

Informations du cercle c1 apres avoir double son rayon : rayon : 4,80

perimetre : 30,16 surface : 72,38

Informations du cercle ayant le rayon le plus grand parmi c1 (modifie) et c2 :

rayon : 4,80 perimetre : 30,16 surface : 72,38 Press any key to continue

*/

(12)

5) Introduction à la notion de propriétés (propertie) :

Le C# propose d’une autre manière pour accéder ou de

modifier les champs privés. Revenez à l’exemple précédent des cercles : au lieu d’écrire deux méthodes GetRayon, SetRayon, le C# propose d’écrire dans la classe Cercle :

public double Rayon {

get { return rayon; } set { rayon = value; } }

Comment utiliser cette méthode ? Dans TestCercle :

- pour afficher le rayon du premier cercle :

Console.WriteLine("Le rayon du cercle c1 presentement : " +

c1.Rayon);

- pour doubler le rayon du premier cercle :

c1.Rayon *= 2.0; // doubler le rayon

et on obtient les mêmes résultats (voir Propriete1.cs sur le site Web du cours).

6) Tableau d’objets :

C’est un tableau dont chaque élément est un objet d’une classe. En C#, comme c’est un langage tout objet, on peut considérer des tableaux de string comme de vrais tableaux d’objets.

La déclaration : Cercle[] tabCer = new Cercle[5]; permet de réserver l’espace de mémoire pour mémoriser 5 éléments, chacun est une référence null au début.

Avec les deux affectations suivantes : tabCer[0] = new Cercle(2.8) ;

tabCer[2] = new Cercle(6.1) ;

on aura le schéma suivant de ce tableau des cercles :

(13)

Dans ce cas ci, tabCer.Length vaut 5 (5 cercles)

Si on déclare et initialise avec la forme complète ( ou raccourcie ) :

Cercle[] tabCer = new Cercle[] = { new Cercle(2.8), new Cercle(4.3), new Cercle(6.1), new Cercle(3.8) };

on aura le schéma suivant :

Exemple de révision :

On réalise la classe Station pour gérer les informations d’une station de métro : son nom, son rang en 2003, sa fréquence en 2004. À travers cette classe, on révise des notions vues y compris l’auto-référence avec this, la propriété, etc.

null null null

tabCer

2.8

6.1

tabCer

2.8

6.1

4.3

3.8

(14)

L’exemple permet aussi de déclarer et de traiter un tableau de stations (voir l’exécution).

/* Fichier Metro.cs (informations sur des stations de métro) *

* Notions de :

* - classe, objet, champ, méthode, ...

* - auto-référence * - propriété

* - tableau d'objets * - etc ...

*

* Voir l'exécution pour le but du programme *

* Préparé par LVN pour IFT 1179 */

using System;

class Station {

private string nom; // nom de la station private int rang2003, // rang en 2003

freq2004; // nb. de passagers aux tourniquets en 2004 // un constructeur possible

public Station(string nom, int rang, int freq2004) {

this.nom = nom;

rang2003 = rang;

this.freq2004 = freq2004;

}

// un autre constructeur possible public Station(string chaine)

{

char[] separateurs = new char[] {'(', ')'};

string[] infosMetro = chaine.Split(separateurs, 3);

nom = infosMetro[0];

rang2003 = int.Parse(infosMetro[1]);

freq2004 = int.Parse(infosMetro[2]);

}

// un constructeur sans paramètre public Station()

{ }

// afficher les infos d'une station public void Afficher(string message) {

Console.WriteLine(message + "{0, -20:S} {1,4:D} {2, 12:N0}", nom, rang2003, freq2004 );

}

(15)

// propriétés : public int Rang {

get { return rang2003; } set { rang2003 = value; } }

public string Nom {

get { return nom; }

set { nom = value.ToUpper(); } }

public int Freq {

get { return freq2004; } set { freq2004 = value; } }

}

class Metro {

static void Demo1() {

Console.WriteLine("Premiere demonstration : " + " notion de classe");

Station stat1 = new Station("COTE-DES-NEIGES(36)3509564");

stat1.Afficher("Infos de station 1 : ");

stat1.Rang -= 10; // correction du rang (26 au lieu de 36) stat1.Afficher("\nInfos de station 1 apres avoir reduit" + " du rang (10 de moins):\n");

Station stat2 = new Station("Plamondon", 11,5021175);

stat2.Afficher("\nInfos (erronees) de station 2 : ");

stat2.Nom = "Jean-TALON"; // corriger le nom de la stat2 stat2.Afficher("\nInfos de station 2 apres avoir " + " change du nom:\n");

Console.WriteLine();

}

static void Afficher(Station[] stat, string mess) {

Console.WriteLine("Informations des stations " + mess);

Console.WriteLine("Rang Nom Rang 2003" + " Freq. 2004");

for(int i = 0; i < stat.Length; i++) {

Console.Write("{0, 3:D}) ", i);

stat[i].Afficher("");

}

Console.WriteLine();

}

(16)

static void AfficherMinMax(Station[] stat, char code) {

int indMin = 0, indMax = 0;

for(int i = 1, nbStat = stat.Length ; i < nbStat; i++) if (code == 'f') // selon les fréquences

{

if (stat[i].Freq < stat[indMin].Freq) indMin = i;

if (stat[i].Freq > stat[indMax].Freq) indMax = i;

} else

{

if (stat[i].Rang < stat[indMin].Rang) indMin = i;

if (stat[i].Rang > stat[indMax].Rang) indMax = i;

}

string sorte = code == 'f' ? "la frequence en 2004" : "le rang en 2003" ;

Console.WriteLine("La station ayant " + sorte + " : ");

stat[indMin].Afficher(" - minimum : ");

stat[indMax].Afficher(" - maximum : ");

Console.WriteLine();

}

static void Demo2() {

Console.WriteLine("Deuxieme demonstration : " + " notion de tableau d'objets\n");

Station[] stat = { new Station("LAURIER(21)3794458"), new Station("VILLA-MARIA", 33, 2753590), new Station("JEAN-TALON(11)5021175"), new Station("DE CASTELNEAU", 52,1391950), new Station("SAINT-MICHEL(19)4063085"), new Station("COTE-DES-NEIGES(26)3509564") };

Afficher(stat, "apres la declaration");

AfficherMinMax(stat, 'f'); // selon les fréquences en 2004 AfficherMinMax(stat, 'r'); // selon les rangs en 2003

}

static void Main(string[] args) {

Demo1();

Demo2();

} }

/* Exécution:

Premiere demonstration : notion de classe

Infos de station 1 : COTE-DES-NEIGES 36 3 509 564 Infos de station 1 apres avoir reduit du rang (10 de moins):

(17)

Infos (erronees) de station 2 : Plamondon 11 5 021 175 Infos de station 2 apres avoir change du nom:

JEAN-TALON 11 5 021 175

Deuxieme demonstration : notion de tableau d'objets Informations des stations apres la declaration Rang Nom Rang 2003 Freq. 2004 0) LAURIER 21 3 794 458 1) VILLA-MARIA 33 2 753 590 2) JEAN-TALON 11 5 021 175 3) DE CASTELNEAU 52 1 391 950 4) SAINT-MICHEL 19 4 063 085 5) COTE-DES-NEIGES 26 3 509 564 La station ayant la frequence en 2004 :

- minimum : DE CASTELNEAU 52 1 391 950 - maximum : JEAN-TALON 11 5 021 175 La station ayant le rang en 2003 :

- minimum : JEAN-TALON 11 5 021 175 - maximum : DE CASTELNEAU 52 1 391 950 Press any key to continue

*/

Références

Documents relatifs

En utilisant le premier paragraphe sur le triangle rectangle on en déduit que la projection du point B sur OP est le cosinus et que la projection de B sur OQ est le sinus, ceci

On considère le cercle C dess- iné ci-contre de centre O.. Quelle particularité possède le

Le triangle DEF est un triangle isocèle en D car les deux côtés [DF ] et [ED] ont la même mesure.. Il semble que le triangle GHI possède un angle droit sur le

[r]

45 La Terre est assimilée à une sphère de rayon 6 371 km. Le mille nautique est une unité de mesure utilisé pour la navigation en mer. Elle correspond à la distance entre deux points

Exercice 2 (8 points) Les calculs devront être expliqués et posés sur la

Il est aussi appelé cercle des 9 points car il passe par les trois pieds des hauteurs, les trois pieds des médianes et les milieux des segments joignant l’orthocentre aux sommets

Penser : pour tracer un polygone régulier : on peut partir du centre et faire des angles de 360. n où n désigne le nombre de côtés du