IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

POO - Comprendre le lien entre set, get et __construct et l'utilité de séparer comme cela


Sujet :

Langage PHP

  1. #1
    Membre régulier
    Inscrit en
    Mai 2008
    Messages
    195
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations forums :
    Inscription : Mai 2008
    Messages : 195
    Points : 82
    Points
    82
    Par défaut POO - Comprendre le lien entre set, get et __construct et l'utilité de séparer comme cela
    Bonjour,

    Je continue mon apprentissage du PHP et notamment de POO.

    Il y a certaines choses que je ne comprends pas, et si je ne les comprends pas, je ne vais pas être en mesure de continuer à avancer correctement.

    1 - Ma première question concerne les fonctions de classe (méthode) et notamment les SET et les GET.

    Dans le programme ci-dessous, j'ai compris que:
    A - Le SET me permet de récupérer une donnée extérieure à ma classe. Et de vérifier si elle correspond bien à un type de donnée attendu.
    B - Le GET "récupererait" la valeur retravaillée pour en faire... ce qu'on a envie d'en faire.

    Question:
    . A quoi me sert-il de passer par les GET Largeur et Longueur?
    Car ici:
    setLongueur et setLargeur modifient la valeur de la propriété longueur et largeur en direct avec $this->longueur(ou largeur)=$longueur(ou$largeur);
    du coup je peux directement récupérer cette valeur directement dans une fonction tiers sans passer par un GET non?
    Dans l'exemple ci-dessous, si je supprime les get largeur/longueur, il n'y a aucune incidence sur le programme.

    S'il a été décidé de mettre des SET et des GET (par convention) il doit donc y avoir une raison qui n'apparait pas dans ce genre de petit exercice pratique.
    Pourriez vous me dire laquelle svp? (Si possible avec un exemple tout simple car j'ai trouvé des explications et je n'ai rien compris )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    <?php
     
    class Pont
    {
    	private float $longueur;
    	private float $largeur;
     
    	private string $unite = ' m²';
     
    	public function setLongueur(float $longueur):void
    	{
    		// Je transforme les données et retourne un résultat
    		if($longueur<0)
    		{
    			trigger_error(
    			'La longueur doit être supérieure à 0.', 
    			E_USER_ERROR
    			);
    		}
     
    		$this->longueur=$longueur;
    	}
     
    	private function getLongueur():float
    	{
    		return $this->longueur;
    	}
     
    	public function setLargeur(float $largeur):void
    	{
    		// Je transforme les données et retourne un résultat
    		if($largeur<0)
    		{
    			trigger_error(
    			'La largeur doit être supérieure à 0.', E_USER_ERROR
    		);
     
    		}
     
    		$this->largeur=$largeur;
    	}
     
    	private function getLargeur():float
    	{
    		return $this->largeur;
    	}
     
    	private function getSurface(): float
        {
            return $this->longueur * $this->largeur;
        }
     
    	public function printSurface():void
    	{
    		echo 'la surface est de '. $this->getSurface().$this->unite;
    	}
     
    }
     
    $towerBridge = new Pont;
    $towerBridge->setLongueur(286.0);
    $towerBridge->setLargeur(15.0);
     
    $towerBridge->printSurface();
    2 - Dans mon second point, je pars du postulat que si la convention passe par une initialisation dans le set et la récupération dans un get, il faut le faire (mais j'aimerai bien comprendre pourquoi cf. question 1 ).

    Autre exercice pour comprendre, je dois écrire un programme de comparaison de deux niveaux de joueurs (jeu), proba de perte/ gain suivant la différence de niveau puis suivant le résultat du "combat", afficher les nouveaux scores.
    Le squelette est donné + formules, j'écris le programme à ma sauce et ça fonctionne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    <?php
     
    // Réponse exercice
    const RESULT_WINNER = 1;
    const RESULT_LOSER = -1;
    const RESULT_DRAW = 0;
    const RESULT_POSSIBILITIES = [RESULT_WINNER, RESULT_LOSER, RESULT_DRAW];
     
    class Encounter
    {
    	public string $playerNameOne;
    	public int $levelOne;
    	public int $resultOne;
     
    	public string $playerNameTwo;
    	public int $levelTwo;
    	public int $resultTwo;
     
    	public function probabilityAgainst($levelOne,$levelTwo):float
    	{
    		return 1/(1+(10 ** (($levelTwo - $levelOne)/400)));
    	}
     
    	public function setNewLevel(&$levelOne, $levelTwo, $resultOne)
    	{
    		if (!in_array($resultOne, RESULT_POSSIBILITIES)) {
    			trigger_error(sprintf('Invalid result. Expected %s',implode(' or ', RESULT_POSSIBILITIES)));
    		}
     
    		return $levelOne += (int) (32 * ($resultOne - $this->probabilityAgainst($levelOne, $levelTwo)));
     
    	}
    }
     
    $players = new Encounter;
     
    $players->playerNameOne="Greg";
    $players->levelOne=400;
    $players->resultOne=RESULT_WINNER;
     
    $players->playerNameTwo="Jade";
    $players->levelTwo=800;
    $players->resultTwo=RESULT_LOSER;
     
     
    echo ($players->probabilityAgainst($players->levelOne,$players->levelTwo)*100).'%';
    echo "</br>";
    echo $players->setNewLevel($players->levelOne,$players->levelTwo,$players->resultOne);
    echo "</br>";
    echo $players->setNewLevel($players->levelTwo,$players->levelOne,$players->resultTwo);
     
    exit(0);
    En revanche, hors cadre car je dois inclure des SET, des GET et un __construct.
    Le programme corrigé est le suivant (pour le coup ce n'est pas le mien):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    <?php
     
    class Encounter
    {
        public const RESULT_WINNER = 1;
        public const RESULT_LOSER = -1;
        public const RESULT_DRAW = 0;
        public const RESULT_POSSIBILITIES = [self::RESULT_WINNER, self::RESULT_LOSER, self::RESULT_DRAW];
     
        public static function probabilityAgainst(Player $playerOne, Player $playerTwo): float
        {
            return 1/(1+(10 ** (($playerTwo->getLevel() - $playerOne->getLevel())/400)));
        }
     
        public static function setNewLevel(Player $playerOne, Player $playerTwo, int $playerOneResult): void
        {
            if (!in_array($playerOneResult, self::RESULT_POSSIBILITIES)) {
                trigger_error(sprintf('Invalid result. Expected %s',implode(' or ', self::RESULT_POSSIBILITIES)));
            }
     
            $playerOne->setLevel(
                $playerOne->getLevel() +
                round(32 * ($playerOneResult - self::probabilityAgainst($playerOne, $playerTwo)))
            );
        }
    }
     
    class Player
    {
        private int $level;
     
        public function __construct(int $level)
        {
            $this->level = $level;
        }
     
        public function getLevel(): int
        {
            return $this->level;
        }
     
        public function setLevel(int $level): void
        {
            $this->level = $level;
        }
    }
     
    $greg = new Player(400);
    $jade = new Player(800);
     
    echo sprintf(
            'Greg à %.2f%% chance de gagner face a Jade',
            Encounter::probabilityAgainst($greg, $jade)*100
        ).PHP_EOL;
     
    // Imaginons que greg l'emporte tout de même.
    Encounter::setNewLevel($greg, $jade, Encounter::RESULT_WINNER);
    Encounter::setNewLevel($jade, $greg, Encounter::RESULT_LOSER);
     
    echo sprintf(
        'les niveaux des joueurs ont évolués vers %s pour Greg et %s pour Jade',
        $greg->getLevel(),
        $jade->getLevel()
    );
     
    exit(0);
    Il y a certaines parties que je n'arrive pas à comprendre:

    A - Ici on place dans Encounter tout ce qui "figé" ou structurel.
    Les règles du jeu, les modèles mathématiques sous jacent ne sont pas sujets à modifs.
    Encounter reçoit les infos depuis les instanciations de la classe Player (quel est le sens de lecture du programme en fait? c'est pas du tout de haut en bas).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    class Encounter
    {
        public const RESULT_WINNER = 1;
        public const RESULT_LOSER = -1;
        public const RESULT_DRAW = 0;
        public const RESULT_POSSIBILITIES = [self::RESULT_WINNER, self::RESULT_LOSER, self::RESULT_DRAW];
     
        public static function probabilityAgainst(Player $playerOne, Player $playerTwo): float
        {
            return 1/(1+(10 ** (($playerTwo->getLevel() - $playerOne->getLevel())/400)));
        }
     
        public static function setNewLevel(Player $playerOne, Player $playerTwo, int $playerOneResult): void
        {
            if (!in_array($playerOneResult, self::RESULT_POSSIBILITIES)) {
                trigger_error(sprintf('Invalid result. Expected %s',implode(' or ', self::RESULT_POSSIBILITIES)));
            }
     
            $playerOne->setLevel(
                $playerOne->getLevel() +
                round(32 * ($playerOneResult - self::probabilityAgainst($playerOne, $playerTwo)))
            );
        }
    }
    La partie que je ne comprends pas est celle-ci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $playerOne->setLevel(
                $playerOne->getLevel() +
                round(32 * ($playerOneResult - self::probabilityAgainst($playerOne, $playerTwo)))
            );

    B - Ici, je ne comprends pas trop le lien entre SET/GET et __construct
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    class Player
    {
        private int $level;
     
        public function __construct(int $level)
        {
            $this->level = $level;
        }
     
        public function getLevel(): int
        {
            return $this->level;
        }
     
        public function setLevel(int $level): void
        {
            $this->level = $level;
        }
    }
     
    $greg = new Player(400);
    $jade = new Player(800);
    . Quel est l'intérêt de passer par __construct? Est-ce seulement pour refiler les données à la fonction en écrivant moins de lignes ou il y a d'autres intérêts?
    Car on a:
    . $greg = new Player(400);
    A la place de:
    $greg = new Player;
    $players->level=400; (si jamais on avait public int $level dans la classe Player - d'ailleurs je ne vois pas trop l'intérêt de le passer en private?)

    . public function __construct(int $level) et public function setLevel(int $level): void, quel est l'intérêt de setLevel dans ce cas?

    C - Dernière partie ou je ne comprends pas un passage
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    echo sprintf(
            'Greg à %.2f%% chance de gagner face a Jade',
            Encounter::probabilityAgainst($greg, $jade)*100
        ).PHP_EOL;
     
    // Imaginons que greg l'emporte tout de même.
    Encounter::setNewLevel($greg, $jade, Encounter::RESULT_WINNER);
    Encounter::setNewLevel($jade, $greg, Encounter::RESULT_LOSER);
     
    echo sprintf(
        'les niveaux des joueurs ont évolués vers %s pour Greg et %s pour Jade',
        $greg->getLevel(),
        $jade->getLevel()
    );
    En première partie j'ai: Encounter::setNewLevel($greg, $jade, Encounter::RESULT_WINNER);
    avec $greg = new Player(400); et la classe Player qui ne contient qu'une seule propriété.
    Du coup j'en ai conclu que lorsque je n'ai qu'une seule propriété, pas besoin de rentrer dans le détail, PHP nous renvoit d'office la valeur de la propriété
    ...
    Sauf que plus bas je trouve:
    $greg->getLevel(), et si je remplace par $greg, ca ne fonctionne pas.

    Du coup, ma théorie précédente tombe à l'eau et je ne vois pas pourquoi dans un cas je peux simplement placer ma variable, et dans l'autre je dois appeler la fonction set.

    C'est un peu long désolé, mais j'essaie de comprendre ca depuis un moment et si je n'arrive pas à clarifier cela, je serai coincé.
    Et je tourne en rond depuis un très looooonnnnngggggg moment désormais.
    J'ai besoin de votre aide.

    D'avance merci pour vos retours

  2. #2
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 705
    Points : 43 785
    Points
    43 785
    Par défaut
    Je suis pas spécialiste en POO mais voilà ce que j'en ai compris.

    Si les propriétés longueur et largeur sont privées, tu ne peux pas y accéder de l’extérieur de l'objet. Quand tu passes par la méthode setlongueur, qui elle a accès à la valeur longueur, celle-ci exécute du code et comme on peut voir vérifie que ta longueur soit supérieure à 0. Si le test passe, la valeur de la propriété est modifiée par le paramètre passé (qui a été vérifié).

    getlongueur ne fait ici rien de précis mais pourrait par exemple retourner la valeur dans une échelle choisie.

    Pour la convention, si tu fais un setter, il est logique de faire un getter. Et ça rend l'éventuelle évolution de l'objet plus simple.
    Pour pouvoir bypasser un get, il faut que tes propriétés soient publiques.

    Quel est l'intérêt de passer par __construct?
    Le constructeur peut être vu comme l'initialisation d'un objet. Dans ton cas longueur/largeur ça va permettre de fixer une valeur par défaut. Un pont a obligatoirement une longueur et une largeur.

    Pour :
    sans fixation de valeur, créerais un joueur avec un level aléatoire, à moins qu'un constructeur fixe un niveau par défaut à ce joueur.

  3. #3
    Membre régulier
    Inscrit en
    Mai 2008
    Messages
    195
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations forums :
    Inscription : Mai 2008
    Messages : 195
    Points : 82
    Points
    82
    Par défaut
    Bonjour chrtophe,

    Merci pour ton retour.
    Même sans être un expert, c'est toujours sympa d'avoir un retour et une explication d'une tierce personne.
    Car quand on a trop le nez dedans c'est délicat de prendre de la hauteur et on finit par être un peu perdu.

    Tes explications me vont bien.
    Ca me permet d'éclaircir l'intérêt et les liens entre les différents éléments.
    Je laisse le sujet ouvert si d'autres retours sur ce sujet.
    Si je vois qu'il n'y a plus de retour je solderai.

    Encore merci

Discussions similaires

  1. Réponses: 1
    Dernier message: 14/11/2011, 08h16
  2. [Débutant] difference entre "set "et "get "
    Par annabiste dans le forum Interfaces Graphiques
    Réponses: 2
    Dernier message: 26/10/2009, 20h55
  3. Lien entre BD, POO et Visual Basic
    Par ArameGaye dans le forum VBA Access
    Réponses: 1
    Dernier message: 12/08/2009, 21h36
  4. Réponses: 3
    Dernier message: 11/04/2004, 01h05
  5. [debutant][servlet]lien entre formulaire et servlet
    Par omega dans le forum Servlets/JSP
    Réponses: 4
    Dernier message: 05/03/2004, 08h54

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo