Selon Herb Sutter, on devrait préférer les interfaces abstraites (toutes les fonctions virtuelles pures) aux classes abstraites en C ++ pour découpler l'implémentation autant que possible. Bien que je trouve personnellement cette règle très utile, j'ai récemment rejoint une équipe avec de nombreux programmeurs Java et dans le code Java, cette directive ne semble pas exister. Les fonctions et leurs implémentations sont très fréquemment situées dans des classes abstraites. Donc, j'ai tout faux Herb Sutter même pour C ++ ou y a-t-il une différence générale dans l'utilisation des fonctions abstraites en C ++ par rapport à Java. Les classes abstraites avec du code d'implémentation sont-elles plus sensées en Java qu'en C ++ et si oui pourquoi?
java
c++
interfaces
abstract-class
Martin
la source
la source
Réponses:
La POO a une composition et une substitution.
C ++ possède plusieurs héritages, une spécialisation de modèle, une intégration et une sémantique de valeur / déplacement / pointeur.
Java possède un héritage et des interfaces uniques, une sémantique d'intégration et de référence.
L'école OOP utilise couramment ces langages pour utiliser l'héritage pour la substitution d'objets et l'incorporation pour la composition. Mais vous avez également besoin d'un ancêtre commun et d'un moyen de lancer le runtime (en C ++ est appelé
dynamic_cast
, en Java, il suffit de demander une interface à un autre).Java fait tout cela par sa propre
java.lang.Object
hiérarchie enracinée. C ++ n'a pas de racine commune prédéfinie, vous devriez donc au moins la définir, pour arriver à une même "image" (mais cela limite certaines possibilités C ++ ...).Après cela, la possibilité d'avoir un polymorphisme au moment de la compilation (pensez au CRTP) et une sémantique de valeur peuvent également offrir d'autres alternatives à la façon dont le concept d '"objet OOP" peut être porté dans un programme C ++.
Vous pouvez même imaginer l'hérésie d'utiliser l'incorporation et la conversion implicite pour gérer la substitution et l'héritage privé pour gérer la composition, en inversant en fait le paradigme scolaire traditionnel. (Bien sûr, cette façon est 20 ans plus jeune que l'autre, alors ne vous attendez pas à un large soutien communautaire pour le faire)
Ou vous pouvez imaginer une base commune virtuelle à toutes les classes, une interface de formulaire (pas d'implémentation) aux classes finales (entièrement implémentées) passant par des interfaces partiellement implémentées et des clusters d'interface pairs, en utilisant la "dominance" comme répartition de l'interface vers les implémentations via un "multi-stacked" -parallelogram "schéma d'héritage.
Comparer OOP à java à C ++ en supposant qu'il n'y a qu'un seul et unique moyen OOP limite les capacités des deux langages.
Forcer C ++ à adhérer strictement aux idiomes de codage Java dénature C ++ car forcer Java à se comporter comme un langage de type C ++ dénature Java.
Ce n'est pas une question de "sensibilité" mais de "mécanismes d'agrégation" différents que les deux langues ont et une manière différente de les combiner qui rend un idiome plus rentable dans une langue que dans l'autre et vice versa.
la source
Le principe est valable pour les deux langues, mais vous ne faites pas une comparaison équitable. Vous devez comparer les classes abstraites pures C ++ avec les interfaces Java.
Même en C ++, vous pouvez avoir des classes abstraites qui ont certaines des fonctions implémentées, mais dérivent d'une classe abstraite pure (pas d'implémentations). En Java, vous auriez les mêmes classes abstraites (avec certaines implémentations), qui peuvent dériver des interfaces (pas d'implémentations).
la source
Généralement, les mêmes principes OO sont valables pour Java et C ++. Cependant, une grande différence est que C ++ prend en charge l'héritage multiple tandis qu'en Java, vous ne pouvez hériter que d'une seule classe. C'est la raison principale pour laquelle Java a des interfaces, je crois, pour compléter le manque d'héritage multiple et probablement pour restreindre ce que vous pouvez en faire (car il y a beaucoup de critiques sur l'abus d'héritage multiple). Donc, probablement dans l'esprit des programmeurs Java, il y a une distinction plus forte entre les classes abstraites et les interfaces. Les classes abstraites sont utilisées pour partager et hériter du comportement tandis que les interfaces sont simplement utilisées pour ajouter des fonctionnalités supplémentaires. N'oubliez pas qu'en Java, vous ne pouvez hériter que d'une seule classe, mais vous pouvez avoir plusieurs interfaces. En C ++ cependant, les classes abstraites pures (c'est-à-dire une "interface C ++") sont utilisé pour partager et hériter d'un comportement contrairement à l'objectif d'une interface Java (même si vous devez toujours implémenter les fonctions), par conséquent, l'utilisation est différente des interfaces Java.
la source
Parfois, il est logique d'avoir une implémentation par défaut. Par exemple, une méthode générique PrintError (string msg) qui s'applique à toutes les sous-classes.
Il peut toujours être remplacé si cela est vraiment nécessaire, mais vous pouvez éviter au client quelques tracas en lui permettant d'appeler simplement la version générique.
la source