web-dev-qa-db-fra.com

Quel est l'avantage de la programmation orientée objet par rapport à la programmation procédurale?

J'essaie de comprendre la différence entre les langages procéduraux comme C et les langages orientés objet comme C++. Je n'ai jamais utilisé C++, mais j'ai discuté avec mes amis de la façon de différencier les deux.

On m'a dit que C++ a des concepts orientés objet ainsi que des modes publics et privés pour la définition des variables: les choses que C n'a pas. Je n'ai jamais eu à les utiliser pendant le développement de programmes dans Visual Basic.NET: quels en sont les avantages?

On m'a également dit que si une variable est publique, elle est accessible n'importe où, mais on ne sait pas en quoi elle est différente d'une variable globale dans un langage comme C. On ne sait pas non plus en quoi une variable privée diffère d'une variable locale.

Une autre chose que j'ai entendue est que, pour des raisons de sécurité, si une fonction doit être accessible, elle doit être héritée en premier. Le cas d'utilisation est qu'un administrateur ne devrait avoir que les droits dont il a besoin et pas tout, mais il semble qu'un conditionnel fonctionnerait également:

if ( login == "admin") {
    // invoke the function
}

Pourquoi n'est-ce pas idéal?

Étant donné qu'il semble y avoir un moyen procédural de tout faire orienté objet, pourquoi devrais-je me préoccuper de la programmation orientée objet?

80
niko

Jusqu'à présent, toutes les réponses se sont concentrées sur le sujet de votre question, à savoir "quelle est la différence entre c et c ++". En réalité, il semble que vous sachiez ce qu'est la différence, vous ne comprenez tout simplement pas pourquoi vous auriez besoin de cette différence. Alors, d'autres réponses ont tenté d'expliquer OO et l'encapsulation.

Je voulais apporter une autre réponse, car sur la base des détails de votre question, je pense que vous devez reculer de plusieurs pas.

Vous ne comprenez pas le but de C++ ou OO, car pour vous, il semble que votre application a simplement besoin de stocker des données. Ces données sont stockées dans des variables. "Pourquoi voudrais-je rendre une variable inaccessible? Maintenant, je ne peux plus y accéder! En rendant tout public, ou mieux encore global, je peux lire des données de n'importe où et il n'y a aucun problème." - Et vous avez raison, compte tenu de l'ampleur des projets que vous écrivez actuellement, il n'y a probablement pas beaucoup de problèmes (ou il y en a, mais vous n'en avez pas encore pris conscience).

Je pense que la question fondamentale à laquelle vous devez vraiment répondre est: "Pourquoi voudrais-je jamais cacher des données? Si je le fais, je ne peux pas travailler avec!" Et c'est pourquoi:

Disons que vous démarrez un nouveau projet, vous ouvrez votre éditeur de texte et vous commencez à écrire des fonctions. Chaque fois que vous avez besoin de stocker quelque chose (pour vous en souvenir pour plus tard), vous créez une variable. Pour simplifier les choses, vous rendez vos variables globales. Votre première version de votre application fonctionne parfaitement. Vous commencez maintenant à ajouter plus de fonctionnalités. Vous avez plus de fonctions, certaines données que vous avez stockées auparavant doivent être lues à partir de votre nouveau code. D'autres variables doivent être modifiées. Vous continuez à écrire plus de fonctions. Ce que vous avez peut-être remarqué (ou, sinon, vous le remarquerez certainement à l'avenir), c'est que, à mesure que votre code grossit, il vous faut de plus en plus longtemps pour ajouter la fonctionnalité suivante. Et à mesure que votre code grossit, il devient de plus en plus difficile d'ajouter des fonctionnalités sans casser quelque chose qui fonctionnait auparavant. Pourquoi? Parce que vous devez vous rappeler ce que tous vos variables globales stockent et vous devez vous rappeler où toutes d'entre elles sont modifiées. Et vous devez vous rappeler quelle fonction est correcte pour appeler quel ordre exact et si vous les appelez dans un ordre différent, vous pourriez obtenir des erreurs parce que vos variables globales ne sont pas tout à fait valable encore. Avez-vous déjà rencontré cela?

Quelle est la taille de vos projets typiques (lignes de code)? Imaginez maintenant un projet 5000 à 50000 fois plus grand que le vôtre. De plus, plusieurs personnes y travaillent. Comment tout le monde dans l'équipe peut-il se souvenir (ou même être au courant) de ce que font toutes ces variables?

Ce que j'ai décrit ci-dessus est un exemple de code parfaitement couplé. Et depuis la nuit des temps (en supposant que le temps a commencé le 1er janvier 1970), le genre humain cherche des moyens d'éviter ces problèmes. La façon de les éviter consiste à diviser votre code en systèmes, sous-systèmes et composants et à limiter le nombre de fonctions ayant accès à n'importe quelle donnée. Si j'ai 5 entiers et une chaîne qui représentent une sorte d'état, serait-il plus facile pour moi de travailler avec cet état si seulement 5 fonctions définissent/obtiennent les valeurs? ou si 100 fonctions définissent/obtiennent ces mêmes valeurs? Même sans OO langages (c'est-à-dire C), les gens ont travaillé dur pour isoler les données des autres données et créer des limites de séparation propres entre les différentes parties du code. Lorsque le projet atteint une certaine taille, la facilité de programmation devient non, "puis-je accéder à la variable X à partir de la fonction Y", mais "comment puis-je m'assurer que seules les fonctions A, B, C et que personne d'autre ne touche la variable X".

C'est pourquoi OO concepts ont été introduits et c'est pourquoi ils sont si puissants. Ils vous permettent de vous cacher vos données et vous voulez de le faire exprès , car moins il y a de code qui voit ces données, moins il y a de chances que, lorsque vous ajoutez la fonctionnalité suivante, vous cassiez quelque chose. C'est le but principal des concepts d'encapsulation et OO Ils vous permettent de décomposer nos systèmes/sous-systèmes en boîtes encore plus granulaires, à un point où, quelle que soit la taille du projet global, un ensemble donné de variables ne peut être consulté que par 50-200 lignes de code et c'est Il y a évidemment beaucoup plus à OO programmation, mais, essentiellement, c'est pourquoi C++ vous donne des options de déclaration de données/fonctions comme privées, protégées ou publiques.

La deuxième plus grande idée de OO est le concept de couches d'abstraction. Bien que les langages procéduraux puissent également avoir des abstractions, en C, un programmeur doit faire un effort conscient pour créer de telles couches, mais en C++, lorsque vous déclarez une classe, vous créez automatiquement une couche d'abstraction (c'est à vous de décider si cette abstraction ajoutera ou supprimera de la valeur). Vous devriez lire/rechercher plus sur les couches d'abstraction et si vous avez plus de questions, je suis sûr que Le forum sera plus qu'heureux d'y répondre également.

138
DXM

Hmm ... il est peut-être préférable de sauvegarder et d'essayer de donner une idée de l'intention de base de la programmation orientée objet. Une grande partie de l'intention de la programmation orientée objet est de permettre la création de types de données abstraits. Pour un exemple vraiment simple avec lequel vous êtes sans aucun doute familier, considérez une chaîne. Une chaîne aura généralement un tampon pour contenir le contenu de la chaîne, certaines fonctions qui peuvent opérer sur la chaîne (la rechercher, y accéder, en créer des sous-chaînes, etc.). Elle aura également (au moins généralement) quelque chose à garder une trace de la longueur (actuelle) de la chaîne et (probablement) de la taille du tampon, donc si (par exemple) vous augmentez la taille de la chaîne de 1 à 1000000, il saura quand il aura besoin de plus de mémoire pour contenir la plus grande contenu.

Ces variables (le tampon, la longueur actuelle et la taille du tampon) sont privées de la chaîne elle-même, mais elles sont pas locales pour une fonction particulière. Chaque chaîne a un contenu d'une certaine longueur, nous devons donc suivre ce contenu/cette longueur pour cette chaîne. Inversement, la même fonction (par exemple, pour extraire une sous-chaîne) peut fonctionner sur de nombreuses chaînes différentes à des moments différents, de sorte que les données ne peuvent pas être locales à la fonction individuelle.

En tant que tel, nous nous retrouvons avec certaines données privées de la chaîne, donc elles ne sont (directement) accessibles qu'aux fonctions de chaîne. Le monde extérieur peut obtenir la longueur de la chaîne à l'aide d'une fonction de chaîne, mais n'a pas besoin de connaître quoi que ce soit sur les éléments internes de la chaîne pour l'obtenir. De même, il peut modifier la chaîne - mais encore une fois, il le fait via les fonctions de chaîne, et seulement ils modifient directement ces variables locales à l'objet chaîne.

En ce qui concerne la sécurité, je noterais que bien que cela soit raisonnable par analogie, c'est pas comment les choses fonctionnent vraiment. En particulier, l'accès en C++ est spécifiquement pas destiné à répondre au même type d'exigences que l'accès dans un système d'exploitation. Un système d'exploitation est censé appliquer les restrictions pour (par exemple) un utilisateur normal ne peut pas faire des choses réservées à un administrateur. En revanche, le contrôle d'accès en C++ vise uniquement à empêcher accidents. De par leur conception, quiconque le souhaite peut les contourner assez facilement. Ils sont dans le même ordre que le marquage d'un fichier en lecture seule afin de ne pas le supprimer accidentellement. Si vous décidez de supprimer le fichier, il est trivial de le changer de lecture seule à lecture-écriture; tout ce qui le définit en lecture seule vous fait au moins y penser une seconde et décider pour supprimer le fichier afin qu'il ne soit pas supprimé par accident simplement en appuyant sur la mauvaise clé au mauvais moment .

10
Jerry Coffin

La POO contre C ne concerne pas vraiment les choses que vous avez discutées. Il s'agit principalement de regrouper le code dans des zones qui ne peuvent/ne peuvent pas involontairement (ou parfois même intentionnellement) s'influencer mutuellement.

C vous permet d'exécuter n'importe quelle fonction depuis n'importe où. OOP empêche cela en regroupant les méthodes en classes et en vous permettant uniquement d'utiliser les méthodes en référençant la classe qui les contient. Donc, un gros avantage potentiel de OOP est que vous êtes beaucoup plus susceptible d'avoir un meilleur arrangement de code sans beaucoup d'expérience pour vous dire que vous devriez.

6
John Fisher

Une classe bien écrite devrait être un petit "îlot de confiance": vous pouvez l'utiliser et supposer qu'elle fait "la bonne chose" et qu'elle vous protège des pièges courants. Cela fait d'une bonne classe un bloc de construction, qui est beaucoup plus réutilisable comme un tas de fonctions et de variables, qui pourrait bien fonctionner mais vous montrer toutes ses tripes laides et vous forcer à comprendre comment elles fonctionnent ensemble, comment elles doivent être initialisées etc. Une bonne classe devrait être comme une prise USB, tandis que la solution procédurale est comme un tas de fils, de puces, d'étain et un peu de soudure.

Un point qui n'a pas été discuté en profondeur est l'aspect interface/implémentation. Une interface décrit le comportement, mais pas la réalisation. Ainsi, une interface de liste décrit le concept d'une liste et son comportement: vous vous attendez à des choses comme les méthodes d'ajout, de suppression et de taille. Maintenant, il existe de nombreuses façons de mettre en œuvre cette liste, par exemple en tant que liste chaînée ou en utilisant un tampon de tableau. La puissance de la programmation OO est qu'en utilisant une interface, vous pouvez raisonner sur le comportement sans connaître l'implémentation. L'accès aux variables ou méthodes internes détruirait cette abstraction, vous ne pouviez pas remplacer une implémentation de liste par un autre, et vous ne pouvez pas améliorer une implémentation existante sans toucher au code à l'aide de la classe. C'est l'une des principales raisons pour lesquelles des variables et des méthodes privées sont nécessaires: pour protéger les détails internes de l'implémentation, afin que l'abstraction reste intacte.

OO va encore plus loin: par ex. pour les bibliothèques, vous pouvez définir une interface pour les choses qui n'existent même pas encore, et écrire du code qui fonctionne avec cette interface. Les utilisateurs peuvent écrire des classes implémentant l'interface et utiliser les services fournis par la bibliothèque. Cela permet un degré de flexibilité qui n'est pas possible avec la programmation procédurale.

4
Landei

Il existe un moyen de tout faire avec une machine Turing, ou au minimum dans un langage d'assemblage pour le code machine qu'un programme C ou C++ compilera finalement.

La différence n'est donc pas ce que le code peut faire, mais ce que les gens peuvent faire.

Les gens font des fautes. Beaucoup.

La POO introduit un paradigme et une syntaxe qui aident à réduire la taille et la densité de probabilité de l'espace des erreurs de codage humaines possibles. Parfois, en rendant l'erreur illégale pour une certaine classe d'objet de données (comme ce n'est pas une méthode déclarée pour cet objet). Parfois, en rendant l'erreur plus verbeuse, ou d'une apparence stylistique par rapport à l'utilisation canonique de la langue. Parfois en exigeant une interface avec beaucoup moins d'incohérences ou d'enchevêtrements possibles (public vs privé). etc.

Plus le projet est grand, plus la probabilité d'erreurs est élevée. À quoi un nouveau codeur pourrait ne pas être exposé s'il n'était expérimenté qu'avec de petits programmes. Ainsi, la perplexité potentielle de savoir pourquoi OOP est précieuse.

3
hotpaw2

Votre question semble plus sur le but de OOP plutôt que sur la différence. Le concept dans votre article est Encapsulation; et l'encapsulation existe pour prendre en charge CHANGE. Lorsque d'autres classes accèdent à vos internes, il devient difficile de modifier Dans OOP vous fournissez une interface (membres publics) à travers laquelle vous autorisez d'autres classes à interagir avec la vôtre, et vous cachez vos internes afin qu'elles puissent être modifiées en toute sécurité.

2
Eoin Carroll

Peu importe où je lis les variables privées ne sont pas accessibles alors que les variables publiques peuvent être alors pourquoi ne pas rendre public aussi global et privé que local quelle est la différence? quelle est l'utilisation réelle du public et du privé? s'il vous plaît ne dites pas qu'il peut être utilisé par tout le monde, je suppose pourquoi ne pas utiliser certaines conditions et passer les appels?

J'espère que vous ne voulez jamais plus d'une chaîne dans votre application. J'espère également que vos variables locales persistent entre les appels de fonction. Ces choses pourraient être les mêmes en termes d'accessibilité, mais en termes de durée de vie et d'autres utilisations? Ce ne sont absolument pas les mêmes.

2
DeadMG

Comme beaucoup l'ont dit, tout programme, une fois compilé, est transformé en code binaire et, comme une chaîne binaire peut être utilisée pour représenter un entier, tout programme n'est finalement qu'un nombre. Cependant, définir le nombre dont vous avez besoin peut être assez difficile et c'est pourquoi des langages de programmation de haut niveau sont apparus. Les langages de programmation ne sont que des modèles du code d'assemblage qu'ils produisent finalement. Je voudrais vous expliquer la différence entre la programmation procédurale et la programmation OO au moyen de ce très bel article sur la programmation contextuelle http://www.jot.fm/issues/issue_2008_03/article4 /

comme vous pouvez le voir sur cette image, décrite dans l'article, la programmation procédurale ne fournit qu'une seule dimension pour associer une unité de calcul à un nom. Ici, les appels de procédure ou les noms sont directement mappés aux implémentations de procédure. Dans la figure-a, l'appel m1 ne laisse d'autre choix que l'invocation de la seule implémentation de la procédure m1.

La programmation orientée objet ajoute une autre dimension pour la résolution de noms à celle de la programmation procédurale. En plus du nom de la méthode ou de la procédure, l'envoi de messages prend en compte le récepteur de messages lors de la recherche d'une méthode. Dans la figure-b, nous voyons deux implémentations de la méthode m1. La sélection de la méthode appropriée dépend non seulement du nom du message m1, mais aussi du destinataire du message réel, ici Ry.

Cela permet en effet l'encapsulation et la modularisation.

enter image description here

La figure-c concerne enfin la programmation orientée sujet qui étend la répartition des méthodes orientées objet par une autre dimension.

J'espère que cela vous a aidé à réfléchir à OOP d'un point de vue différent.

1
Andrea Sindico

(+ 1) Poser une question sur quelque chose que vous ne comprenez pas, c'est bien, même si cela semble idiot.

La différence est la programmation orientée objet et classe. "Plain C", fonctionne avec les données et les fonctions. "C++" ajoute les concepts "objet et classes", ainsi que plusieurs concepts secondaires associés.

Cependant, je recommande aux développeurs d'apprendre "Plain C" avant "C++". Ou "Pascal procédural" avant "Object Pascal".

De nombreux développeurs pensent que les étudiants ne devraient enseigner qu'une seule chose.

Par exemple, de vieux professeurs qui n'obtiennent pas O.O., et n'enseignent que "Plain Structured C".

Ou des professeurs "hipster" qui n'enseignent que l'O.O., mais pas "Plain C", parce que "vous n'en avez pas besoin". Ou les deux, sans se soucier de l'ordre d'enseignement.

Je pense plutôt que les étudiants devraient apprendre à la fois le "Structured Plain C" et le "Object Oriented C (C++)". Avec "Plain C", en premier, et "C++", plus tard.

Dans le monde réel, vous devez apprendre les deux paradigmes (ainsi que d'autres paradigmes, comme "fonctionnel").

Penser les programmes structurés comme un grand "objet" singleton peut aider.

Vous devez également mettre l'accent dans les espaces de noms ("modules"), dans les deux langues, de nombreux enseignants l'ignorent, mais c'est important.

0
umlcat

En un mot, la gestion de projet. Ce que je veux dire, c'est que C++ m'aide à appliquer les règles d'utilisation de mon code par les autres. Travaillant sur un projet de 5,5 millions de lignes, je trouve la programmation orientée objet très utile. Un autre avantage est le compilateur qui me fait (et tout le monde) suivre certaines règles et détecter des erreurs mineures au moment de la compilation. Tous les avantages théoriques sont là aussi, mais je voulais juste me concentrer sur les choses pratiques de tous les jours. Après tout, tout se compile en code machine.

0
Gus