D'accord, cela me dérange vraiment et je commence à penser que tout se résume à un choix personnel plutôt qu'à une manière particulière d'être plus efficace ou d'écrire un meilleur code: devrais-je ou ne devrais-je pas utiliser des méthodes getter/setter dans un PHP? Les réponses que j'ai lues jusqu'à présent sont plutôt contradictoires et ne conviennent pas entièrement à PHP, qui n'est pas un langage compilé. Par exemple, prenez cette question sur Stack Overflow (" Pourquoi utiliser des getters et setters ?"). Il y a un certain nombre de bonnes raisons présentées pour lesquelles je devrais les utiliser dans mon code, mais tous les commentaires des enfants mentionnent comment Les accesseurs sont mauvais et doivent être évités, entrecoupés de quelques commentaires plus inquiétants qui mentionnent que ils doivent être évités entièrement car cela "détruit votre code".
Tout ce que je reçois, ce sont des réponses contradictoires, dont aucune n'est pertinente pour un environnement PHP interprété. Quelqu'un peut-il expliquer pourquoi/pourquoi ne pas les utiliser dans PHP, et leur justification derrière cette décision? Est-ce vraiment important si nous pouvons simplement définir une propriété comme privée ou protégée et, de toute façon:
Les getters et setters d'encapsulation sont ridiculement minces
... cité de "sbi" (Pourquoi utiliser des getters et setters?)
Personnellement, je ne vois toujours pas comment:
Class Foo {
public $bar;
function setBarType($val) {
$this->bar = $val;
}
}
$fee = new Foo();
$fee->setBarType(42);
est supérieur à cela:
Class Foo {
public $bar;
}
$fee = new Foo();
$fee->bar = 42;
Parce que si l'implémentation de la façon dont la valeur est définie change (en db), vous n'avez pas à changer les appelants. Un autre exemple est que vous devrez peut-être vérifier la valeur avant de la définir.
Avoir une méthode vous permet d'intercepter le réglage/obtention de cette variable, le faire quand il ne semble pas que vous en ayez besoin rend votre code plus convivial.
Des langages comme C # et les versions récentes de JavaScript vous permettent d'intercepter la lecture et l'écriture de propriétés, vous pouvez donc simplement utiliser les propriétés dans les langages qui le prennent en charge.
Certains langages vous permettent d'intercepter la lecture/le réglage de tous Object.watch de JavaScript , ou des propriétés inaccessibles avec __get de PHP . Cela vous permet d'implémenter des getters et setters, mais vous obtenez un impact sur les performances en raison de la surcharge qu'ils créent pour chaque accès à la propriété. Cette réponse parle d'autres problèmes avec les getters et les setters. Meilleure pratique: PHP Méthodes magiques __set et __get
Faire des getters et setters passe-partout est mieux, mais c'est presque aussi mauvais que les propriétés publiques. Si quelqu'un peut changer l'état de votre objet (spécialement avec plusieurs propriétés), il ne sera pas bien encapsulé. http://cspray.github.io/2012/05/13/stop-calling-them-getters-setters.html
Le billet de blog auquel vous avez lié commence par une phrase cruciale (soulignement ajouté):
Chaque getter et setter de votre code représente un échec de l'encapsulation et crée un couplage inutile.
L'encapsulation est l'idée la plus importante de la programmation orientée objet. Il se résume essentiellement à cacher la complexité en l'enveloppant soigneusement dans les classes. Dans un monde idéal, lorsque vous utilisez une classe, vous ne devriez pas avoir à connaître quoi que ce soit sur son fonctionnement interne ou son état. Certaines personnes (comme cet auteur de blog) diront que le fait d'avoir des getters et des setters est déjà beaucoup trop d'informations sur l'intérieur de la classe. À leur avis, une classe ne devrait avoir que des méthodes qui nous permettent de dire à un objet de faire quelque chose, peu importe comment elle le fait ou son état in. Utiliser un setter ne signifie pas "dire à l’objet de faire quelque chose", c’est déformer l’état de l’objet de l’extérieur.
Au lieu de faire ceci:
$a = myObject();
// Querying object state, making a decision outside the object, and changing its state
if ($a->getWarbleFizz() < 42) {
$a->setYourWarbleFizzTo(42);
}
// Gee, I hope I made the right decision...
$a->nowDoSomethingUseful();
Vous devriez écrire du code comme ceci:
$a = myObject(42);
$a->doStuff();
Ou ca :
$a = myObject();
$a->doStuff(42);
Lecture connexe: Dites, ne demandez pas .
Un grand avantage de l'utilisation d'un getter et d'un setter est que, chaque fois que vous devez apporter des modifications, vous n'avez qu'à modifier le getter et le setter.
Je vais essayer d'expliquer avec un exemple:
protected $date;
public function getDate(){
return $this->date;
}
public function setDate($date){
$this->date = $date;
}
Imaginez qu'il y ait une raison pour laquelle la date devrait toujours être incrémentée d'un jour. Vous devrez rechercher dans l'ensemble de votre projet où vous avez accédé à votre membre de classe.
Mais en utilisant des getters et setters vous pouvez changer le code en:
protected $date;
public function getDate(){
return $this->date;
}
public function setDate($date){
$date = new DateTime($date);
$date->modify('+1 day');
$this->date = $date;
}
Un principe OOP est l'encapsulation. Une classe est responsable de toutes les variables contenues dans cette classe.
En définissant une variable publique, vous cassez ce principe.
En créant un accesseur (setter), vous brisez indirectement ce principe en donnant une chance à cette valeur d'être modifiée en dehors de la classe.
L'avantage d'un getter est que la méthode d'appel n'a pas besoin de se soucier de la façon dont les données sont récupérées. Il sait seulement qu'il obtiendra les données attendues et c'est tout. Ici, le principe d'encapsulation est respecté.
L'avantage d'un setter est que la classe a la possibilité de vérifier la nouvelle valeur avant de l'appliquer. Dans un monde parfait, il n'y a pas besoin d'accesseurs car une classe peut gérer entièrement toutes ses variables. Dans le monde réel, vous devez parfois définir une valeur ou l'obtenir de l'extérieur.
La meilleure façon d'approcher le monde parfait est de ne limiter les accesseurs qu'aux très rares variables à modifier. Et vérifiez les valeurs réglées si possible.
À propos de votre exemple, la deuxième solution est meilleure car vous enregistrez un niveau dans la pile php. Votre accesseur est inutile car votre variable est de toute façon publique (donc, pas d'encapsulation) et n'effectuez aucune vérification supplémentaire. Mais lorsque cela est possible, vous DEVEZ utiliser un accessoire pour vérifier les données. Si les données ne sont nécessaires nulle part ailleurs dans votre application, ne faites aucun accessoire.
Le choix vous appartient. Les autres fonctionnalités importantes de PHP 5 à considérer sont les getter/setters magiques:
http://www.php.net/manual/en/language.oop5.overloading.php#object.sethttp://www.php.net/manual/en/ language.oop5.overloading.php # object.get
La magie de ceci est que vous pouvez faire quelque chose comme ce qui suit et décider où obtenir/définir des variables sans avoir à les déclarer au préalable:
Class Foo {
private $data = array();
function __set($name,$val) {
$this->$data[$name] = $val;
}
function __get($name) {
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
else {
return null;
}
}
Voila, quelque chose comme ça se produit maintenant automatiquement:
$ fee = new Foo (); $ frais-> bar = 42;
Si vous n'utilisez pas les getters et les setters dans un langage comme PHP, qui n'est pas sûr pour le type, comment allez-vous vous assurer que le type de la propriété de l'objet est correct?
Je manque peut-être complètement le point, mais si vous avez besoin d'accéder à une propriété de l'extérieur de l'objet, je pense que c'est toujours la meilleure option pour utiliser des accesseurs ...
En outre, comme le mentionne Juon Mendes: certaines langues vous proposent d'intercepter lorsque les propriétés elles-mêmes sont traitées. Cela peut également arriver sur PHP
Vous pouvez même avoir un setter public et un getter protégé:
class TimePeriod {
protected $Seconds = 3600;
public $Hours {
get { return $this->Seconds / 3600; }
set { $this->Seconds = $value * 3600; }
}
// This property is read only as there is no setter
public $Minutes {
get { return $this->Seconds / 60; }
}
/* public getter, protected setter */
public $Milliseconds {
get { return $this->Seconds * 1000; }
protected set { $this->Seconds = $value / 1000; }
}
}
IMO utilisant des getters et setters est une bonne pratique et augmente également la lisibilité du code. Outre la vérification de la valeur lors de la définition, il existe un autre exemple, à savoir si vous appelez getMoviesList()
. Maintenant, cette méthode get peut être implémentée de toute façon, elle peut obtenir la liste des films à partir de la base de données locale, l'obtenir à partir du service Web en ligne, etc. D'où que vous l'appeliez, vous ne vous souciez pas de l'emplacement et de la façon dont il est obtenu. U juste obtenez la liste des films.