Code comme:
public Thing[] getThings(){
return things;
}
Cela n'a pas beaucoup de sens, car votre méthode d'accès ne fait que renvoyer directement la structure de données interne. Vous pourriez tout aussi bien déclarer Thing[] things
être public
. L'idée derrière une méthode d'accès est de créer une interface qui isole les clients des changements internes et les empêche de manipuler la structure de données réelle, sauf de manière discrète comme le permet l'interface. Comme vous l'avez découvert lorsque tout votre code client s'est cassé, votre méthode d'accès ne l'a pas fait - c'est juste du code gaspillé. Je pense que beaucoup de programmeurs ont tendance à écrire du code comme ça parce qu'ils ont appris quelque part que tout doit être encapsulé avec des méthodes d'accès - mais c'est pour les raisons que j'ai expliquées. Le faire simplement pour «suivre le formulaire» lorsque la méthode d'accès ne sert à rien n'est que du bruit.
Je recommanderais certainement votre solution proposée, qui atteint certains des objectifs les plus importants de l'encapsulation: Donner aux clients une interface robuste et discrète qui les isole des détails d'implémentation interne de votre classe et ne leur permet pas de toucher la structure de données interne attendez de la manière que vous jugez appropriée - "la loi du moindre privilège". Si vous regardez les grands frameworks OOP populaires, tels que le CLR, le STL, le VCL, le modèle que vous avez proposé est répandu, pour exactement cette raison.
Faut-il toujours faire ça? Pas nécessairement. Par exemple, si vous avez des classes d'assistance ou d'amis qui sont essentiellement un composant de votre classe de travail principale et qui ne sont pas "orientées vers l'avant", ce n'est pas nécessaire - c'est une surpuissance qui va ajouter beaucoup de code inutile. Et dans ce cas, je n'utiliserais pas du tout de méthode d'accès - c'est insensé, comme expliqué. Déclarez simplement la structure de données d'une manière qui ne s'applique qu'à la classe principale qui l'utilise - la plupart des langues prennent en charge des façons de le faire - friend
, ou la déclarez dans le même fichier que la classe de travail principale, etc.
Le seul inconvénient que je peux voir dans votre proposition, c'est que c'est plus de travail à coder (et maintenant vous allez devoir recoder vos classes de consommateurs - mais vous devez / devez le faire de toute façon.) Mais ce n'est pas vraiment un inconvénient - vous devez le faire correctement, et cela prend parfois plus de travail.
L'une des choses qui rendent un bon programmeur bon, c'est qu'il sait quand le travail supplémentaire en vaut la peine et quand il ne l'est pas. À long terme, le fait de verser un supplément maintenant rapportera de gros dividendes à l'avenir - sinon sur ce projet, puis sur d'autres. Apprenez à coder la bonne façon et à utiliser votre tête à ce sujet, pas seulement à suivre de manière robotique les formulaires prescrits.
Notez que les collections plus complexes que les tableaux peuvent nécessiter que la classe englobante implémente encore plus de trois méthodes juste pour accéder à la structure de données interne.
Si vous exposez une structure de données entière à travers une classe contenante, OMI, vous devez réfléchir à la raison pour laquelle cette classe est encapsulée, si ce n'est pas simplement pour fournir une interface plus sûre - une "classe wrapper". Vous dites que la classe conteneur n'existe pas à cette fin - alors peut-être qu'il y a quelque chose qui ne va pas dans votre conception. Pensez à diviser vos classes en modules plus discrets et à les superposer.
Une classe doit avoir un objectif clair et discret, et fournir une interface pour prendre en charge cette fonctionnalité - pas plus. Vous essayez peut-être de regrouper des choses qui ne vont pas ensemble. Lorsque vous faites cela, les choses se brisent à chaque fois que vous devez mettre en œuvre un changement. Plus vos classes sont petites et discrètes, plus il est facile de changer les choses: pensez à LEGO.
get(index)
,add()
,size()
,remove(index)
etremove(Object)
. En utilisant la technique proposée, la classe qui contient cette ArrayList doit avoir cinq méthodes publiques juste pour déléguer à la collection interne. Et le but de cette classe dans le programme est très probablement de ne pas encapsuler cette ArrayList, mais plutôt de faire autre chose. L'ArrayList n'est qu'un détail. [...]