2010-08-17 11 views
1

Possible en double:
Public Data members vs Getters, SettersDans quels cas les champs publics devraient-ils être utilisés à la place des propriétés?

Dans quels cas doivent être utilisés champs publics, au lieu de propriétés ou méthodes getter et setter (où il n'y a pas de support pour les propriétés)? Où leur utilisation est-elle recommandée, et pourquoi, ou, si ce n'est pas le cas, pourquoi sont-ils toujours autorisés en tant qu'élément de langue? Après tout, ils cassent le principe d'encapsulation orienté objet où les getters et setters sont autorisés et encouragés.

Répondre

2

qui est difficile à dire, mais à mon avis les champs publics ne sont valables que lors de l'utilisation struct .

struct Simple 
{ 
    public int Position; 
    public bool Exists; 
    public double LastValue; 
}; 

Mais différentes personnes ont des idées différentes sur:

http://kristofverbiest.blogspot.com/2007/02/public-fields-and-properties-are-not.html

http://blogs.msdn.com/b/ericgu/archive/2007/02/01/properties-vs-public-fields-redux.aspx

http://www.markhneedham.com/blog/2009/02/04/c-public-fields-vs-automatic-properties/

+0

Une autre exception que je ferais dans .net serait quelque chose comme une classe «MutableHolder » dont le seul but est d'exposer un champ public de type «T».Envelopper des éléments de collection compatibles Interlocked dans une telle classe lorsque vous les stockez dans une collection, il sera possible d'utiliser des méthodes 'Interlocked' même si la collection ne supporte pas ce genre de choses, et envelopper les types de valeur dans ces classes permettra les modifier "directement" sans modifier la collection sous-jacente. On peut contenir plus d'un élément dans l'objet de classe en utilisant un PODS de champ exposé comme paramètre de type. – supercat

4

Si vous avez une constante devant être publique, vous pouvez aussi en faire un champ public au lieu de créer une propriété getter. En dehors de cela, je n'en vois pas la nécessité, en ce qui concerne les bons principes de la POO.

Ils sont là et autorisés parce que parfois vous avez besoin de la flexibilité.

+0

+1 pour avoir lu dans mes pensées :) –

+0

Je ne suis pas sûr qu'une constante publique soit toujours souhaitable. À ce stade, une telle valeur fait partie de l'API et vous ne pouvez probablement pas la supprimer/la modifier facilement. – soulmerge

1

Si votre compilateur n'optimise pas les invocations getter et setter, l'accès à vos propriétés peut être plus coûteux que la lecture et l'écriture de champs (pile d'appels). Cela pourrait être pertinent si vous effectuez beaucoup, beaucoup d'invocations.

Mais, pour être honnête, je ne connais aucun langage où cela soit vrai. Au moins dans .NET et Java ceci est bien optimisé.

D'un point de vue de la conception que je ne connais aucun cas où l'utilisation des champs est recommandé ...

Vive Matthias

1

Let premier regard sur la question pourquoi nous avons besoin accesseurs (getters/setters) ? Vous en avez besoin pour pouvoir remplacer le comportement lorsque vous attribuez une nouvelle valeur/lisez une valeur. Vous pouvez ajouter une mise en cache ou renvoyer une valeur calculée au lieu d'une propriété.

Votre question peut maintenant être formée comme est-ce que je veux toujours ce comportement? Je peux penser à des cas où cela n'est pas du tout utile: structures (struct s en C). Le passage d'un parameter object ou d'une classe enveloppant plusieurs valeurs à insérer dans un Collection sont des cas où l'on n'a pas réellement besoin d'accesseurs: L'objet est simplement un conteneur pour les variables.

1

Il y a une seule raison (*) pourquoi utiliser get à la place du champ public: évaluation paresseuse. C'est à dire. la valeur que vous voulez peut être stockée dans une base de données, ou peut être longue à calculer, et ne veut pas que votre programme l'initialise au démarrage, mais seulement lorsque cela est nécessaire.

Il y a une seule raison (*) pourquoi utiliser un ensemble au lieu d'un champ public: d'autres modifications de champs. C'est à dire. vous changez la valeur des autres champs lorsque vous modifiez la valeur du champ cible.

Obligation d'utiliser obtenir et définir sur chaque champ est en en contradiction avec le YAGNI principe.

Si vous souhaitez exposer la valeur d'un champ d'un objet, puis l'exposer! Il est complètement inutile de créer un objet avec quatre champs indépendants et d'exiger que tous utilisent l'accès à get/set ou aux propriétés.

*: D'autres raisons, telles qu'un changement de type de données possible, sont inutiles. En fait, partout où vous utilisez a = o.get_value() au lieu de a = o.value, si vous changez le type retourné par get_value() vous devez changer à chaque utilisation, comme si vous auriez changé le type de value.

+0

Je ne pense pas que YAGNI va aussi loin que «peut-être que le code d'appel n'aura pas besoin de fonctionner lorsque nous publierons une version plus récente de ce composant». Je serais à peu près sûr qu'ils en auront besoin, et vous devez donc réfléchir à la possibilité de changer un champ en une propriété à l'avance, car un tel changement casserait le code d'appel. –

+0

Tout comme vous avez écrit, vous êtes * assez sûr *. YAGNI dit que tant que vous n'en avez pas réellement besoin, vous ne l'écrivez pas. –

+0

J'ai dit "assez sûr" pour la valeur de l'humour. Je suis certain à 100% que si je met à niveau un composant et que beaucoup d'autres composants cessent de fonctionner, je ne serai pas content. Je ne sais pas si je vais avoir besoin d'un changement donné, mais s'il est impossible de faire ce changement sans casser le code, il y a des limites sur YAGNI. –

0

La raison principale n'est pas liée à l'encapsulation OOP (bien que les gens disent souvent que c'est le cas), et tout à voir avec le versioning. En effet, à partir de la position OOP, on pourrait dire que les champs sont meilleurs que les propriétés «aveugles», car un manque d'encapsulation est plus clair que quelque chose qui fait semblant d'être encapsulé et ensuite le souffle. Si l'encapsulation est importante, alors il devrait être bon de voir quand elle n'est pas là.

Une propriété appelée Foo ne sera pas traitée de la même manière de l'extérieur qu'un champ public appelé Foo. Dans certaines langues, cela est explicite (le langage ne supporte pas directement les propriétés, donc vous avez un getFoo et un setFoo) et dans certains cas il est implicite (C# et VB.NET supportent directement les propriétés, mais ils ne sont pas compatibles binaires avec les champs et le code compilés pour utiliser un champ va se casser s'il est changé en propriété, et vice-versa).

Si votre Foo fait juste un ensemble "aveugle" et écris un champ sous-jacent, alors il n'y a actuellement aucun avantage d'encapsulation à pour exposer le champ. Cependant, s'il y a une exigence ultérieure de tirer parti de l'encapsulation pour éviter les valeurs invalides (vous devriez toujours empêcher les valeurs invalides, mais peut-être vous ne l'avez pas réalisé lorsque vous avez écrit la classe, ou peut-être "a changé avec un changement d'étendue), pour encapsuler l'évaluation memoised, pour déclencher d'autres changements dans l'objet, pour déclencher un événement on-change, pour éviter des ensembles inutiles coûteux et ainsi de suite, alors vous ne pouvez pas faire ce changement sans casser le code courant.

Si la classe est interne au composant en question, ce n'est pas un problème, et je dirais utiliser des champs si les champs lisent raisonnablement selon le principe général de YAGNI. Cependant, YAGNI ne joue pas si bien à travers les frontières des composants (si j'avais besoin de mon composant pour fonctionner aujourd'hui, je vais probablement avoir besoin que ça fonctionne demain après que vous ayez changé le composant dont dépend le mien), il peut donc être judicieux d'utiliser les propriétés de manière préventive.

+0

Au moins dans .net, si le type en question est une structure dont l'état est exposé via des propriétés/champs pouvant être lus publiquement, et peut être défini, peut-être via le constructeur, pour prendre des combinaisons de valeurs valables pour leurs types respectifs, les propriétés offrent presque aucun avantage d'encapsulation, mais ont des inconvénients importants. – supercat

Questions connexes