Comment accéderiez-vous aux propriétés d'un objet à partir d'une méthode d'objet? [fermé]

96

Quelle est la manière "puriste" ou "correcte" d'accéder aux propriétés d'un objet à partir d'une méthode objet qui n'est pas une méthode getter / setter?

Je sais que de l'extérieur de l'objet, vous devriez utiliser un getter / setter, mais de l'intérieur, vous feriez simplement:

Java:

String property = this.property;

PHP:

$property = $this->property;

ou feriez-vous:

Java:

String property = this.getProperty();

PHP:

$property = $this->getProperty();

Pardonnez-moi si mon Java est un peu décalé, cela fait un an que je programme en Java ...

ÉDITER:

Il semble que les gens supposent que je parle uniquement de variables / propriétés privées ou protégées. Quand j'ai appris OO, on m'a appris à utiliser des getters / setters pour chaque propriété même si elle était publique (et en fait, on m'a dit de ne jamais rendre publique une variable / propriété). Donc, je pars peut-être d'une fausse hypothèse dès le départ. Il semble que les gens qui répondent à cette question disent peut-être que vous devriez avoir des propriétés publiques et que celles-ci n'ont pas besoin de getters et de setters, ce qui va à l'encontre de ce qu'on m'a appris et de ce dont je parlais, même si cela doit peut-être être discuté comme bien. C'est probablement un bon sujet pour une question différente cependant ...

cmcculloh
la source

Réponses:

62

Cela a un potentiel de guerre religieuse, mais il me semble que si vous utilisez un getter / setter, vous devriez également l'utiliser en interne - utiliser les deux entraînera des problèmes de maintenance plus tard (par exemple, quelqu'un ajoute du code à un setter qui a besoin à exécuter chaque fois que cette propriété est définie et que la propriété est définie en interne sans que le setter soit appelé).

Greg Hurlman
la source
ne fait rien d'autre dans un setter que de définir la valeur de la propriété, un exemple d'utilisation incorrecte en Java.
euphoria83
1
@ euphoria83 Peut-être, mais cela ne l'empêche pas de se produire.
Greg Hurlman
Je suis d'accord avec la réponse originale. Cependant, rappelez-vous simplement que si vous définissez ou obtenez quelque chose de privé dans la classe ou l'objet, vous devez vous assurer que le getter / setter n'est pas cyclique ou redondant d'une manière qui provoque l'échec de votre code. Si vous ne pouvez pas utiliser le getter / setter, accédez-y directement. (Ex. Votre getter / setter accède à une méthode secondaire (privée / protégée) pour manipuler les données.)
Rick Mac Gillis
43

Personnellement, je pense qu'il est important de rester cohérent. Si vous avez des getters et des setters, utilisez-les. Le seul moment où j'accéderais directement à un champ est lorsque l'accesseur a beaucoup de frais généraux. Vous aurez peut-être l'impression de gonfler votre code inutilement, mais cela peut certainement vous éviter beaucoup de maux de tête à l'avenir. L'exemple classique:

Plus tard, vous souhaiterez peut-être changer la façon dont ce champ fonctionne. Il devrait peut-être être calculé à la volée ou peut-être souhaitez-vous utiliser un type différent pour le magasin de support. Si vous accédez directement aux propriétés, un changement comme celui-ci peut briser énormément de code en un seul coup.

MojoFilter
la source
26

Je suis assez surpris de voir à quel point le sentiment est unanime getterset que les setters sont bons et bons. Je suggère l'article incendiaire d'Allen Holub " Getters And Setters Are Evil ". Certes, le titre est pour la valeur de choc, mais l'auteur fait valoir des points valables.

Essentiellement, si vous avez getterset setterspour chaque champ privé, vous rendez ces champs aussi bons que publics. Vous auriez beaucoup de mal à changer le type d'un champ privé sans effets d'entraînement pour chaque classe qui l'appelle getter.

De plus, d'un point de vue strictement OO, les objets devraient répondre à des messages (méthodes) qui correspondent à leur (espérons-le) responsabilité unique. La grande majorité getterset settersn'ont pas de sens pour leurs objets constitutifs; Pen.dispenseInkOnto(Surface)a plus de sens pour moi que Pen.getColor().

Les getters et les setters encouragent également les utilisateurs de la classe à demander à l'objet des données, à effectuer un calcul, puis à définir une autre valeur dans l'objet, mieux connue sous le nom de programmation procédurale. Vous feriez mieux de dire simplement à l'objet de faire ce que vous alliez faire en premier lieu; également connu sous le nom d' idiome Information Expert .

Les getters et les setters, cependant, sont des maux nécessaires à la frontière des couches - UI, persistance, etc. L'accès restreint aux éléments internes d'une classe, tels que le mot-clé friend de C ++, l'accès protégé par package Java, l'accès interne de .NET et le modèle de classe Friend peut vous aider à réduire la visibilité getterset les setters à ceux qui en ont besoin.

moffdub
la source
19

Cela dépend de la façon dont la propriété est utilisée. Par exemple, supposons que vous ayez un objet étudiant qui a une propriété de nom. Vous pouvez utiliser votre méthode Get pour extraire le nom de la base de données, s'il n'a pas déjà été récupéré. De cette façon, vous réduisez les appels inutiles à la base de données.

Maintenant, disons que vous avez un compteur d'entiers privés dans votre objet qui compte le nombre de fois où le nom a été appelé. Vous souhaiterez peut-être ne pas utiliser la méthode Get à l'intérieur de l'objet car elle produirait un décompte non valide.

Shawn
la source
Si l'objet Student est un objet métier / domaine, vous mélangez maintenant les détails de l'infrastructure. Idéalement, les objets métier / domaine ne devraient concerner que la logique métier / domaine.
moffdub le
Que faire si vous ajoutez une sorte de booléen au getter comme: PHP: public function getName ($ outsideCall = true) {if ($ outsideCall) {$ this-> incrementNameCalled (); } retourne $ this-> nom; } puis depuis l'objet lui-même, si vous appelez get name, vous pouvez l'empêcher de s'incrémenter en: PHP: $ name = $ this-> getName (false); Est-ce que je vais juste trop loin ici?
cmcculloh
14

PHP offre une myriade de façons de gérer cela, y compris des méthodes magiques __getet __set, mais je préfère les getters et les setters explicites. Voici pourquoi:

  1. La validation peut être placée dans les setters (et les getters d'ailleurs)
  2. Intellisense fonctionne avec des méthodes explicites
  3. Pas question de savoir si une propriété est en lecture seule, en écriture seule ou en lecture-écriture
  4. La récupération des propriétés virtuelles (c'est-à-dire des valeurs calculées) ressemble à des propriétés normales
  5. Vous pouvez facilement définir une propriété d'objet qui n'est jamais réellement définie nulle part, qui devient alors non documentée
Viande non étiquetée
la source
13

Est-ce que je vais juste trop loin ici?

Peut-être;)

Une autre approche consisterait à utiliser une méthode privée / protégée pour effectuer réellement l'obtention (mise en cache / db / etc), et un wrapper public pour cela qui incrémente le compte:

PHP:

public function getName() {
    $this->incrementNameCalled();
    return $this->_getName();
}

protected function _getName() {
    return $this->name;
}

puis de l'intérieur de l'objet lui-même:

PHP:

$name = $this->_getName();

De cette façon, vous pouvez toujours utiliser ce premier argument pour autre chose (comme envoyer un indicateur pour savoir s'il faut ou non utiliser les données mises en cache ici peut-être).

pix0r
la source
12

Je dois manquer le point ici, pourquoi utiliseriez-vous un getter dans un objet pour accéder à une propriété de cet objet?

Prenant cela à sa conclusion, le getter devrait appeler un getter, qui devrait appeler un getter.

Donc, je dirais qu'à l'intérieur d'une méthode objet, accéder directement à une propriété, d'autant plus que l'appel d'une autre méthode dans cet objet (qui accédera simplement à la propriété directement de toute façon puis la retournera) est juste un exercice inutile et inutile (ou ai-je mal compris la question ).

Vans à œufs
la source
J'étais motivé par le même besoin que vous aviez de commenter ... De plus, il a été répondu non fermé;)
Egg Vans
8

La manière puriste OO est d'éviter les deux et de suivre la loi de Déméter en utilisant l' approche Tell Don't Ask .

Au lieu d'obtenir la valeur de la propriété de l'objet, qui couple étroitement les deux classes, utilisez l'objet comme paramètre, par exemple

  doSomethingWithProperty() {
     doSomethingWith( this.property ) ;
  }

Lorsque la propriété était de type natif, par exemple int, utilisez une méthode d'accès, nommez-la pour le domaine de problème et non pour le domaine de programmation.

  doSomethingWithProperty( this.daysPerWeek() ) ;

Celles-ci vous permettront de maintenir l'encapsulation et toutes les post-conditions ou invariants dépendants. Vous pouvez également utiliser la méthode setter pour maintenir toutes les pré-conditions ou invariants dépendants, mais ne tombez pas dans le piège de les nommer setters, revenez au principe d'Hollywood pour nommer lorsque vous utilisez l'idiome.

Martin Spamer
la source
8

Il est préférable d'utiliser les méthodes d'accesseur, même dans l'objet. Voici les points qui me viennent immédiatement à l'esprit:

  1. Cela doit être fait dans l'intérêt de maintenir la cohérence avec les accès effectués depuis l'extérieur de l'objet.

  2. Dans certains cas, ces méthodes d'accès pourraient faire plus que simplement accéder au champ; ils pourraient effectuer un traitement supplémentaire (c'est rare cependant). Si tel est le cas, accéder directement au champ signifierait que vous manquez ce traitement supplémentaire, et votre programme pourrait mal tourner si ce traitement doit toujours être effectué pendant ces accès.

Aadith Ramia
la source
8

Si vous voulez dire «la plupart de l'encapsulation» par «puriste», alors je déclare généralement tous mes champs comme privés et j'utilise ensuite «this.field» depuis la classe elle-même. Pour les autres classes, y compris les sous-classes, j'accède à l'état de l'instance en utilisant les getters.

Allain Lalonde
la source
7

J'ai trouvé que l'utilisation de setters / getters rendait mon code plus facile à lire. J'aime aussi le contrôle qu'il donne lorsque d'autres classes utilisent les méthodes et si je change les données, la propriété stockera.

Brendon-Van-Heyzen
la source
7

Champs privés avec propriétés publiques ou protégées. L'accès aux valeurs doit passer par les propriétés et être copié dans une variable locale si elles seront utilisées plusieurs fois dans une méthode. Si et UNIQUEMENT si vous avez le reste de votre application si totalement modifié, secoué et autrement optimisé pour que l'accès aux valeurs en passant par leurs propriétés associées est devenu un goulot d'étranglement (et cela ne se produira JAMAIS, je vous le garantis) si vous commencez même d'envisager de laisser autre chose que les propriétés toucher directement leurs variables de support.

Les développeurs .NET peuvent utiliser des propriétés automatiques pour appliquer cela, car vous ne pouvez même pas voir les variables de sauvegarde au moment du design.

Mel
la source
7

Ça dépend. C'est plus une question de style qu'autre chose, et il n'y a pas de règle absolue.

Steve McLeod
la source
7

Je peux me tromper car je suis autodidacte, mais je n'utilise JAMAIS de propriétés publiques dans mes classes Java, elles sont toujours privées ou protégées, de sorte que le code extérieur doit y accéder par les getters / setters. C'est mieux à des fins de maintenance / modification. Et pour le code de classe interne ... Si la méthode getter est triviale, j'utilise la propriété directement, mais j'utilise toujours les méthodes setter car je pourrais facilement ajouter du code pour déclencher des événements si je le souhaite.

Telcontar
la source
7

Si je ne modifie pas la propriété, j'utiliserai une méthode publique à get_property()moins que ce ne soit une occasion spéciale telle qu'un objet MySQLi à l'intérieur d'un autre objet, auquel cas je rendrai simplement la propriété publique et y ferai référence $obj->object_property.

À l'intérieur de l'objet, c'est toujours la propriété $ this-> pour moi.

Ross
la source
5

Eh bien, il semble qu'avec l'implémentation par défaut des propriétés C # 3.0, la décision est prise pour vous; vous DEVEZ définir la propriété en utilisant le setter de propriétés (éventuellement privé).

Personnellement, je n'utilise le membre privé derrière que si cela ne ferait pas tomber l'objet dans un état moins que souhaitable, comme lors de l'initialisation ou lorsque la mise en cache / le chargement paresseux est impliqué.

Coincoin
la source
5

J'aime la réponse de cmcculloh , mais il semble que la plus correcte soit la réponse de Greg Hurlman . Utilisez getter / setter tout le temps si vous avez commencé à les utiliser dès le départ et / ou si vous êtes habitué à travailler avec eux.

En passant, je trouve personnellement que l'utilisation de getter / setter rend le code plus facile à lire et à déboguer plus tard.

Robinho
la source
4

Comme indiqué dans certains des commentaires: Parfois, vous devriez, parfois vous ne devriez pas. L'avantage des variables privées est que vous pouvez voir tous les endroits où elles sont utilisées lorsque vous changez quelque chose. Si votre getter / setter fait quelque chose dont vous avez besoin, utilisez-le. Si cela n'a pas d'importance, vous décidez.

Le cas contraire pourrait être fait que si vous utilisez le getter / setter et que quelqu'un change le getter / setter, ils doivent analyser tous les endroits où le getter et le setter sont utilisés en interne pour voir si cela gâche quelque chose.

svrist
la source