Le développement Java implique-t-il généralement plus de sous-classes que C # / .NET?

34

J'ai récemment commencé à regarder le développement Android. Cela m'a ramené dans le monde du développement de logiciels Java. La dernière fois que j’ai travaillé avec Java, je l’avouerai, je ne comprenais pas autant la POO que je le pense maintenant.

Ayant principalement utilisé le C # dans ma carrière, je remarque une différence surprenante dans l'utilisation de l'héritage en Java et C #.

En C #, il semblait que l'héritage pouvait être évité dans la plupart des situations. La tâche à accomplir peut généralement être accomplie en utilisant des classes concrètes du framework .NET .

En Java, d'après ce que je récupère à partir d'exemples de code, le framework Java fournit de nombreuses interfaces ou classes abstraites qui doivent ensuite être implémentées / étendues par le développeur.

Cela semble être une trop grande différence pour se résumer à un style. Quel est le raisonnement derrière cela? Je sens que je n'écrirai pas de code Java propre tant que je ne l'aurai pas compris.

En outre, est-ce limité au SDK Android ou s'agit-il d'une approche de la POO à l'échelle de Java?

Ou en d'autres termes,

Qu'y a-t-il dans la conception de ces deux langages qui (semble encourager) l'utilisation plus ou moins héréditaire de l'autre?

Si les langues traitent l'héritage de manière identique, et en supposant que mon observation soit valide, cela signifie alors que cela est lié à la conception des frameworks / bibliothèques et non aux langues. Quelle serait la motivation pour ce type de design?

MetaFight
la source
1
C'est vrai. Java a beaucoup trop d'interfaces. J'aimerais savoir pourquoi ce comportement de développeur est commun à un langage spécifique. Je vois cela se produire plus souvent dans les projets Java que dans les autres. Il doit y avoir une raison à cela et pas seulement un avis.
Reactgular
1
@ MathewFoscarini, ce n'est que votre opinion . Dans les projets Java auxquels j'ai participé, les développeurs étaient enclins à éviter l'héritage comme une peste. Rien d'autorité ici, seulement mon opinion . Vous voulez voter ?
moucher
2
Vous n'avez presque jamais besoin de dériver une classe d'une autre en Java. Au lieu de cela, vous pouvez implémenter des interfaces pour réaliser un polymorphisme et implémenter des objets composés et proxy les appels de méthode pour obtenir une fonctionnalité shaired.
DwB
1
@ThinkingMedia En général, Java est envahi par les fanatiques / puristes de l'OSS. Les principes académiques sont la préoccupation primordiale. Les développeurs .Net sont des pragmatiques soucieux de faire le travail. Ils valorisent le code de travail plus que le code le plus propre.
Andy

Réponses:

31

Cela semble être une trop grande différence pour se résumer à un style. Quel est le raisonnement derrière cela?

Je crois comprendre qu'il en grande partie est tout simplement une décision stylistique. Eh bien, peut-être pas le style, mais les idiomes de la langue / de l'environnement. Les développeurs de bibliothèques standard Java ont suivi un ensemble de directives de conception et les développeurs .NET un autre (bien qu’ils aient eu la possibilité de voir comment l’approche de Java fonctionnait).

Il y a très peu de choses dans les langues actuelles pour encourager ou dissuader l'héritage. Deux choses me semblent pertinentes:

  1. .NET a introduit les génériques plus tôt dans leur vie, avant que trop de code non générique ne soit implémenté. L'alternative est beaucoup d'héritage pour taper des choses spécialisées.

  2. Un changement plus important a été que les délégués soutenus par .NET. En Java, l'héritage (anonyme) vous empêche de fournir les fonctionnalités de base les plus élémentaires. Cela conduit à une différence relativement importante dans la manière dont le code est conçu pour tirer parti des délégués ou pour éviter les structures d'héritage fastidieuses nécessaires pour le faire en Java.

Telastyn
la source
3
Je pense que cette réponse offre une explication très plausible. Surtout le point sur l'héritage anonyme à la place des délégués. J'ai beaucoup observé ça. Merci.
MetaFight
3
N'oubliez pas les types anonymes et les arbres de syntaxe / expression lambda introduits dans .NET 3.5. Et bien sûr, optez pour la dactylographie dynamique dans .NET 4. C'est maintenant presque incontestablement un langage à paradigme mixte, et non strictement orienté objet.
Aaronaught
oui, dans mon expérience, ayant utilisé les deux (y compris sur des projets mixtes où les mêmes personnes utilisent les deux langues), les gens ont tendance à préférer utiliser un plus grand nombre de classes plus petites pour coder Java, un nombre plus petit de classes plus grandes (tendance aux classes divines) lorsque en utilisant C #. Si vous prototypez délibérément la même chose en utilisant le même style dans les deux cas, vous obtenez un nombre similaire de classes (avec des classes partielles, vous obtiendrez probablement davantage de fichiers de code, même si vous utilisez C #).
Jwenting
6

Ce sont des langues très différentes, particulièrement dans ce domaine. Disons que vous avez une classe. Dans ce cas, nous allons en faire un contrôle utilisateur, quelque chose comme une zone de texte. Appelez-le UIControl. Maintenant, nous voulons mettre cela dans une autre classe. Dans ce cas, puisque nous utilisons une interface utilisateur pour notre exemple, nous l'appellerons la classe CleverPanel. Notre instance CleverPanel voudra savoir ce qui se passe dans son instance UIControl pour diverses raisons. Comment faire ça?

En C #, l’approche de base consiste à rechercher différents événements, en définissant des méthodes à exécuter lorsque chaque événement intéressant est déclenché. En Java, où il manque des événements, la solution habituelle consiste à transmettre un objet avec différentes méthodes de traitement "d'événement" à une méthode UIControl:

boolean  stillNeedIt =  ... ;
uiControl.whenSomethingHappens( new DoSomething()  {
    public void resized( Rectangle r )  { ... }
    public boolean canICloseNow()  { return !stillNeedIt; }
    public void closed()  { ... }
    ...
} );

Jusqu'à présent, la différence entre C # et Java n'est pas profonde. Cependant, nous avons l'interface DoSomething qui n'est pas nécessaire en C #. En outre, cette interface peut inclure de nombreuses méthodes qui ne sont pas nécessaires la plupart du temps. En C #, nous ne gérons tout simplement pas cet événement. En Java, nous créons une classe qui fournit une implémentation nulle pour toutes les méthodes d'interface, DoSomethingAdapter. Maintenant, nous remplaçons DoSomething par DoSomethingAdapter et nous n’avons besoin d’écrire aucune méthode pour une compilation propre. Nous finissons par ignorer les méthodes dont nous avons besoin pour que le programme fonctionne correctement. Nous finissons donc par avoir besoin d’une interface et d’ utiliser l’héritage en Java pour correspondre à ce que nous avons fait avec les événements en C #.

Ceci est un exemple, pas une discussion exhaustive, mais il explique en gros pourquoi il y a tant d'héritage en Java par opposition à C #.

Maintenant, pourquoi Java fonctionne-t-il de cette façon? Souplesse. L'objet transmis à whenSomethingHappens aurait pu être transmis à CleverPanel d'un autre endroit complètement. Plusieurs instances de CleverPanel doivent peut-être passer à leurs objets de type UIControl pour aider un objet CleverWindow quelque part. Ou bien UIControl pourrait le transférer à l’un de ses composants.

En outre, au lieu d'un adaptateur, il peut exister une implémentation de DoSomething comportant des milliers de lignes de code. Nous pourrions créer une nouvelle instance de cela et la transmettre. Nous pourrions avoir besoin de remplacer une méthode. Une astuce courante en Java est d’avoir une grande classe avec une méthode comme:

public class BigClass implements DoSomething  {
    ...many long methods...
    protected int getDiameter()  { return 5; }
}

Puis dans CleverlPanel:

uiControl.whenSomethingHappens( new BigClass()  {
    @Override
    public int getDiameter()  { return UIPanel.currentDiameter; }
} );

La plate-forme Java open source fait beaucoup de cela, ce qui a tendance à pousser les programmeurs à en faire plus - à la fois parce qu'ils suivent l'exemple et simplement pour l'utiliser. Je pense que la conception de base du langage repose sur la conception de la structure de Sun et sur celle du programmeur Java qui utilise les techniques sans utiliser la structure.

Il est très facile de créer une classe à la volée en Java. La classe, anonyme ou nommée, ne doit être référencée que dans un petit bloc de code enfoui au cœur d'une méthode. Il peut être créé complètement nouveau ou par de légères modifications d'une très grande classe existante. (Et la classe existante peut être de niveau supérieur dans son propre fichier, ou imbriquée dans une classe de niveau supérieur, ou définie uniquement dans un seul bloc de code). La nouvelle instance de classe peut avoir un accès complet à toutes les données de l'objet en cours de création. Et la nouvelle instance peut être transmise et utilisée dans tout le programme, représentant l'objet qui l'a créée.

(Soit dit en passant, notez qu'une grande utilisation de l'héritage ici - comme dans d'autres endroits en Java - est simplement destinée à la DRY. Cela permet à différentes classes de réutiliser le même code. Notez également la facilité d'héritage en Java qui l'encourage. )

Encore une fois, ce n’est pas une discussion complète; Je ne fais que gratter la surface ici. Mais oui, il existe une différence surprenante dans l'utilisation de l'héritage entre Java et C #. Ce sont des langues très différentes à cet égard. Ce n'est pas ton imagination.

RalphChapin
la source
Remarque: Vous pouvez éviter de fournir des méthodes inutiles en étendant une classe abstraite pleine d'implémentations vides. De cette façon, vous pouvez remplacer sélectivement les méthodes qui font quelque chose. Bien que moins moche, cela signifie un autre niveau d'héritage.
Peter Lawrey
-2

Il n'y a absolument aucune différence dans la gestion de l'héritage entre Java et C #. Lorsque vous utiliserez réellement l'héritage ou la composition, cela est définitivement une décision de conception et, en aucun cas, quelque chose que Java ou C # encourage ou décourage. Je vous suggère de lire cet article .

J'espère que j'ai aidé!

Pantelis Natsiavas
la source
5
Vous parlez des langues elles-mêmes, mais je pense que la question concerne également les bibliothèques et leur usage courant.
svick
3
Mais il y a bizarreries dans le reste du langage qui encouragent un héritage supplémentaire en Java; Voir la réponse de
RalphChapin