Maison développement back-end Golang Introduction à la programmation orientée objet (POO) en Golang

Introduction à la programmation orientée objet (POO) en Golang

Dec 23, 2024 pm 12:43 PM

Quand nous parlons de programmation, nous entendons généralement écrire un tas de fonctions qui modifient et interagissent avec certaines données. La programmation orientée objet (POO) est un modèle de programmation qui se concentre plutôt sur des « objets » qui contiennent des données et auxquels sont attachées certaines fonctions pertinentes. La programmation orientée objet repose sur quatre piliers : l'héritage, l'encapsulation, le polymorphisme et l'abstraction. Dans ce blog, nous verrons comment vous pouvez implémenter chacun d'eux dans Golang avec des exemples. Une idée de base sur la POO est recommandée, mais sinon, je donnerai une brève introduction à la signification des quatre piliers.

Introduction to Object Oriented Programming (OOP) in Golang

Classes, objets et méthodes

L'idée centrale de la programmation orientée objet peut être résumée dans ces puces :

  • Vous définissez des « classes » qui sont un ensemble de données et de fonctions que vous pouvez appeler sur ces données.
  • Ces fonctions spécifiques sont appelées « méthodes » de cette classe particulière.
  • Une instance réelle d'une classe est appelée un « objet ».

Regardons du code en Golang pour comprendre ces trois concepts :

package main

import "fmt"

type Batman struct {
    actor string
    year int
}

func (b Batman) SayImBatman() {
    fmt.Printf("I'm %s and I'm Batman from year %d\n", b.actor, b.year)
}

func main() {
    b1 := Batman{actor: "Michael Keaton", year: 1989}
    b2 := Batman{actor: "Christian Bale", year: 2005}

    b1.SayImBatman()
    b2.SayImBatman()
}

Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans Golang, les classes ne sont que des types définis par nos soins. Ces types ne doivent pas nécessairement être une structure, mais ils le sont généralement car en POO, nous travaillons avec une collection de données, qui peuvent être de n'importe quel type (chaîne, int, etc.).

Les classes sont des plans d'objets. Chaque fois que vous instanciez une classe, un objet est formé. Dans cet exemple, b1 et b2 sont des objets de la classe Batman.

La fonction SayImBatman peut être appelée sur n'importe quel objet de la classe. Puisqu'elle est liée à la classe Batman, au lieu de l'appeler une fonction normale, on l'appelle une méthode de la classe.

Je pense que cela devrait clarifier suffisamment les bases de la POO pour que vous puissiez passer à la section suivante, où nous examinons les quatre piliers de la POO.

Héritage

L'héritage introduit les concepts de classes parent et enfant en POO. Une classe enfant est une classe dérivée d'une classe parent et hérite de toutes ses méthodes et propriétés (données). Regardons un code qui nous aidera à comprendre ceci :

package main

import "fmt"

type Hero struct {
    team string
}

type Batman struct {
    Hero
    name string
}

type Ironman struct {
    Hero
    power int
}

func (h Hero) SayTeam() {
    fmt.Println("My Team is", h.team)
}

func (b Batman) SayImBatman() {
    fmt.Printf("I'm %s and I'm Batman\n", b.name)
}

func (i Ironman) SayPowerLevel() {
    fmt.Printf("I'm Ironman and my powerlevel is %d\n", i.power)
}

func main() {
    b1 := Batman{Hero{team: "Justice League"}, "Christian Bale"}
    i1 := Ironman{Hero{team: "Avengers"}, 23}

    b1.SayImBatman()
    b1.SayTeam()

    i1.SayPowerLevel()
    i1.SayTeam()
}

Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans cet exemple, Batman et Ironman sont des classes enfants de la classe parent Hero. Ils ont accès aux propriétés de leur classe parent, c’est-à-dire team, et à ses méthodes, c’est-à-dire SayTeam. Comme vous pouvez le voir lors de la déclaration des instances b1 et i1, nous spécifions les propriétés de la classe parent ainsi que leurs propriétés spécifiques pour les classes respectives. Les deux sont capables d’appeler la méthode SayTeam définie sur la classe parent. Mais ils ont aussi des propriétés et des méthodes distinctes qui sont propres à chacun d'eux.

Golang implémente l'héritage en utilisant la composition (en utilisant une structure à l'intérieur d'une structure). Il n'a pas d'héritage intégré basé sur les classes comme les autres langages POO tels que C ou Java.

Encapsulation

L'encapsulation est le principe qui consiste à masquer les propriétés internes d'un objet et à ne pas permettre leur modification directe. Au lieu de cela, il repose sur la fourniture de méthodes pour obtenir et mettre à jour ces propriétés. Regardons un exemple pour mieux comprendre cela :

package main

import "fmt"

type Batman struct {
    actor string
    year int
}

func (b Batman) SayImBatman() {
    fmt.Printf("I'm %s and I'm Batman from year %d\n", b.actor, b.year)
}

func main() {
    b1 := Batman{actor: "Michael Keaton", year: 1989}
    b2 := Batman{actor: "Christian Bale", year: 2005}

    b1.SayImBatman()
    b2.SayImBatman()
}

Copier après la connexion
Copier après la connexion
Copier après la connexion
package main

import "fmt"

type Hero struct {
    team string
}

type Batman struct {
    Hero
    name string
}

type Ironman struct {
    Hero
    power int
}

func (h Hero) SayTeam() {
    fmt.Println("My Team is", h.team)
}

func (b Batman) SayImBatman() {
    fmt.Printf("I'm %s and I'm Batman\n", b.name)
}

func (i Ironman) SayPowerLevel() {
    fmt.Printf("I'm Ironman and my powerlevel is %d\n", i.power)
}

func main() {
    b1 := Batman{Hero{team: "Justice League"}, "Christian Bale"}
    i1 := Ironman{Hero{team: "Avengers"}, 23}

    b1.SayImBatman()
    b1.SayTeam()

    i1.SayPowerLevel()
    i1.SayTeam()
}

Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans Golang, les propriétés et méthodes exportées hors du package commencent par une lettre majuscule. Lorsque nous définissons l'acteur et l'année avec une minuscule dans le package utils, nous nous assurons qu'ils ne peuvent pas être modifiés directement. Au lieu de cela, comme vous le voyez dans le fichier main.go, vous devez utiliser les méthodes exportées (qui commencent par une lettre majuscule) - GetActor, SetActor, etc., pour les récupérer et les modifier.

C'est à cela que sert l'encapsulation : s'assurer que vous évitez les modifications accidentelles des données et fournissez plutôt des méthodes pour interagir en toute sécurité avec les données.

Une chose que vous remarquerez différente est que dans toutes les méthodes de la classe Batman, nous utilisons un récepteur de pointeur *Batman au lieu d'un récepteur de valeur Batman comme nous l'étions dans les exemples précédents. En effet, nous voulons pouvoir modifier la structure d'origine dans les méthodes Set. Et dans Golang, il est recommandé que si certaines méthodes nécessitent un récepteur de pointeur, vous fassiez en sorte que toutes les méthodes utilisent un récepteur de pointeur pour des raisons de cohérence. C'est pourquoi les méthodes Get utilisent également un récepteur de pointeur même si elles ne modifient pas la structure d'origine.

En outre, une autre chose à noter est que, simplement parce que nous utilisons un récepteur pointeur, nous n'avons pas à faire ceci : (&b1).GetActor. En Golang, les fonctions avec un argument pointeur doivent prendre un pointeur, mais les méthodes avec un récepteur pointeur peuvent prendre une valeur ou un pointeur comme récepteur.

TL;DR : Golang traduit automatiquement b1.GetActor par (&b1).GetActor puisque la méthode GetActor a un récepteur de pointeur, mais elle ne traduirait pas GetActor(b1) en GetActor(&b1) si GetActor avait été une fonction normale prenant un argument de pointeur.

Polymorphisme et abstraction

Les deux prochains piliers de la POO peuvent être matraqués car les exemples de code correspondants seraient assez similaires. Le polymorphisme fait référence à la pratique de programmation dans laquelle deux objets différents de deux classes différentes peuvent être traités comme des objets de la même superclasse commune. Cela signifie que vous pouvez appeler la même fonction sur deux objets différents comme s'il s'agissait d'objets de la même classe. Cela devrait commencer à vous donner une idée des interfaces impliquées :)

Regardons un peu de code pour mieux comprendre cela :

package main

import "fmt"

type Batman struct {
    actor string
    year int
}

func (b Batman) SayImBatman() {
    fmt.Printf("I'm %s and I'm Batman from year %d\n", b.actor, b.year)
}

func main() {
    b1 := Batman{actor: "Michael Keaton", year: 1989}
    b2 := Batman{actor: "Christian Bale", year: 2005}

    b1.SayImBatman()
    b2.SayImBatman()
}

Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans cet exemple, la fonction StartFight peut recevoir à la fois les objets b1 et i1 même s'ils ne sont en aucun cas liés les uns aux autres. Essayez de comprendre en quoi cela est différent de l'héritage, où les classes enfants avaient accès aux méthodes de la classe parent. Dans cet exemple, il n'y a pas de classes enfants et parents (et aucune méthode n'est également partagée). Au lieu de cela, deux objets différents sont traités comme identiques par une fonction : c'est ce qu'on appelle le polymorphisme.

Maintenant, cela peut également être traité comme un exemple d’abstraction. L'abstraction, comme son nom l'indique, est la pratique de programmation consistant à cacher les détails d'implémentation et à simplement fournir des fonctions qui s'occupent des choses à votre place. Dans cet exemple, vous n’avez pas besoin de vous soucier de la configuration des méthodes de chaque héros. Vous pouvez continuer à utiliser la fonction StartFight chaque fois que vous souhaitez utiliser l’une des fonctions Fight des héros. De cette façon, les détails de mise en œuvre restent cachés à l'utilisateur et seuls les détails essentiels sont exposés.

Pour en revenir maintenant au polymorphisme, il existe deux exemples plus courants, à savoir le remplacement de méthode et la surcharge.

Remplacement de méthode

Le remplacement de méthode fait référence aux classes enfants définissant leur propre implémentation des méthodes définies sur la classe parent. Cette implémentation est désormais utilisée à la place de l’implémentation de la classe parent d’origine. Prenons le code que nous avons utilisé pour l'héritage plus tôt et voyons à quoi il ressemble avec le remplacement de méthode :

package main

import "fmt"

type Hero struct {
    team string
}

type Batman struct {
    Hero
    name string
}

type Ironman struct {
    Hero
    power int
}

func (h Hero) SayTeam() {
    fmt.Println("My Team is", h.team)
}

func (b Batman) SayImBatman() {
    fmt.Printf("I'm %s and I'm Batman\n", b.name)
}

func (i Ironman) SayPowerLevel() {
    fmt.Printf("I'm Ironman and my powerlevel is %d\n", i.power)
}

func main() {
    b1 := Batman{Hero{team: "Justice League"}, "Christian Bale"}
    i1 := Ironman{Hero{team: "Avengers"}, 23}

    b1.SayImBatman()
    b1.SayTeam()

    i1.SayPowerLevel()
    i1.SayTeam()
}

Copier après la connexion
Copier après la connexion
Copier après la connexion

Le résultat de ce programme est :

//oops-in-go/utils/utils.go

package utils

type Batman struct {
    actor string
    year int
}

func (b *Batman) GetActor() string {
    return b.actor
}

func (b *Batman) GetYear() int {
    return b.year
}

func (b *Batman) SetActor(actor string) {
    b.actor = actor
}

func (b *Batman) SetYear(year int) {
    b.year = year
}
Copier après la connexion

Les objets de la classe Batman utilisent désormais leur propre méthode SayTeam au lieu de celle de la classe Hero parent. Étant donné que la classe Ironman n'a pas de méthode SayTeam propre, son objet utilise toujours la méthode de sa classe parent. C'est ce que signifie le remplacement de méthode, les classes enfants « remplaçant » les méthodes définies sur la classe parent.

Surcharge de méthode

Cela fait référence à la même fonction pouvant prendre plusieurs arguments différents. Ces arguments peuvent être différents en nombre ou en type. Golang propose deux manières d'y parvenir : via des fonctions variadiques et l'autre via des interfaces.

Regardons le code des deux, qui vous aidera à mieux comprendre :

Utilisation de fonctions variadiques

// oops-in-go/main.go

package main

import (
    "fmt"
    "oops-in-go/utils"
)

func main() {
    b1 := utils.Batman{}
    b1.SetActor("Michael Keaton")
    b1.SetYear(1989)
    fmt.Printf("I'm %s and I'm Batman from year %d\n", b1.GetActor(), b1.GetYear())

    b1.SetActor("Christian Bale")
    b1.SetYear(2005)
    fmt.Printf("I'm %s and I'm Batman from year %d\n", b1.GetActor(), b1.GetYear())
}

Copier après la connexion

Ici, vous pouvez « surcharger » la fonction listMembers avec n'importe quel nombre d'arguments.

Utilisation des interfaces

package main

import "fmt"

type Hero interface {
    Fight()
}

type Batman struct {
    weapon string
}

type Ironman struct {
    weapon string
}

func (b Batman) Fight() {
    fmt.Printf("Batman hits with a %s\n", b.weapon)
}

func (i Ironman) Fight() {
    fmt.Printf("Ironman hits with a %s\n", i.weapon)
}

func StartFight(h Hero) {
    fmt.Println("Fight has started.")
    h.Fight()
}

func main() {
    b1 := Batman{"Batarang"}
    i1 := Ironman{"Repulsor rays"}

    StartFight(b1)
    StartFight(i1)
}

Copier après la connexion

Le résultat de ce programme est :

package main

import "fmt"

type Hero struct {
    team string
}

type Batman struct {
    Hero
    name string
}

type Ironman struct {
    Hero
    power int
}

func (h Hero) SayTeam() {
    fmt.Println("My Team is", h.team)
}

func (b Batman) SayImBatman() {
    fmt.Printf("I'm %s and I'm Batman\n", b.name)
}

func (i Ironman) SayPowerLevel() {
    fmt.Printf("I'm Ironman and my powerlevel is %d\n", i.power)
}

func (b Batman) SayTeam() {
    fmt.Printf("I'm Batman and my team is %s\n", b.team)
}

func main() {
    b1 := Batman{Hero{team: "Justice League"}, "Christian Bale"}
    i1 := Ironman{Hero{team: "Avengers"}, 23}

    b1.SayImBatman()
    b1.SayTeam()

    i1.SayPowerLevel()
    i1.SayTeam()
}

Copier après la connexion

Ici, nous « surchargeons » la méthode saySomething pour prendre des arguments de différents types. Nous prenons une interface vide comme argument, qui peut être de n'importe quel type, puis vérifions son type à l'aide d'un boîtier de commutation et imprimons la sortie en conséquence.

Conclusion

Je suis bien conscient que cette lecture a été longue, et si vous êtes resté jusqu'au bout, sachez que je suis vraiment heureux :) J'espère sincèrement que vous avez appris beaucoup de nouvelles choses sur la programmation orientée objet et comment l'implémenter dans Golang. J'écris des blogs sur différents concepts techniques sur mon site Web, et si vous souhaitez apprendre de nouvelles choses, je vous recommande de vous inscrire à ma newsletter.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Tutoriel Java
1653
14
Tutoriel PHP
1251
29
Tutoriel C#
1224
24
Objectif de Golang: Construire des systèmes efficaces et évolutifs Objectif de Golang: Construire des systèmes efficaces et évolutifs Apr 09, 2025 pm 05:17 PM

GO Language fonctionne bien dans la construction de systèmes efficaces et évolutifs. Ses avantages incluent: 1. Haute performance: compilé en code machine, vitesse de course rapide; 2. Programmation simultanée: simplifier le multitâche via les goroutines et les canaux; 3. Simplicité: syntaxe concise, réduction des coûts d'apprentissage et de maintenance; 4. Plate-forme multipliée: prend en charge la compilation multiplateforme, déploiement facile.

Golang et C: concurrence vs vitesse brute Golang et C: concurrence vs vitesse brute Apr 21, 2025 am 12:16 AM

Golang est meilleur que C en concurrence, tandis que C est meilleur que Golang en vitesse brute. 1) Golang obtient une concurrence efficace par le goroutine et le canal, ce qui convient à la gestion d'un grand nombre de tâches simultanées. 2) C Grâce à l'optimisation du compilateur et à la bibliothèque standard, il offre des performances élevées près du matériel, adaptées aux applications qui nécessitent une optimisation extrême.

Golang vs Python: différences et similitudes clés Golang vs Python: différences et similitudes clés Apr 17, 2025 am 12:15 AM

Golang et Python ont chacun leurs propres avantages: Golang convient aux performances élevées et à la programmation simultanée, tandis que Python convient à la science des données et au développement Web. Golang est connu pour son modèle de concurrence et ses performances efficaces, tandis que Python est connu pour sa syntaxe concise et son écosystème de bibliothèque riche.

Golang vs Python: performance et évolutivité Golang vs Python: performance et évolutivité Apr 19, 2025 am 12:18 AM

Golang est meilleur que Python en termes de performances et d'évolutivité. 1) Les caractéristiques de type compilation de Golang et le modèle de concurrence efficace le font bien fonctionner dans des scénarios de concurrence élevés. 2) Python, en tant que langue interprétée, s'exécute lentement, mais peut optimiser les performances via des outils tels que Cython.

La course de performance: Golang vs C La course de performance: Golang vs C Apr 16, 2025 am 12:07 AM

Golang et C ont chacun leurs propres avantages dans les compétitions de performance: 1) Golang convient à une concurrence élevée et à un développement rapide, et 2) C fournit des performances plus élevées et un contrôle fin. La sélection doit être basée sur les exigences du projet et la pile de technologie d'équipe.

Impact de Golang: vitesse, efficacité et simplicité Impact de Golang: vitesse, efficacité et simplicité Apr 14, 2025 am 12:11 AM

GOIMIMPACTSDEVENCEMENTSPOSITIVEMENTS INSPECT, EFFICACTION ET APPLICATION.1) VITESSE: GOCOMPILESQUICKLYANDRUNSEFFIÉMENT, IDEALFORLARGEPROROSTS.2) Efficacité: ITSCOMPEHENSIVESTANDARDLIBRARYREDUCEEXTERNEDENDENCES, EnhancingDevelovefficiency.3) Simplicité: Simplicité: Implicité de la manière

C et Golang: Lorsque les performances sont cruciales C et Golang: Lorsque les performances sont cruciales Apr 13, 2025 am 12:11 AM

C est plus adapté aux scénarios où le contrôle direct des ressources matérielles et une optimisation élevée de performances sont nécessaires, tandis que Golang est plus adapté aux scénarios où un développement rapide et un traitement de concurrence élevé sont nécessaires. 1.C's Avantage est dans ses caractéristiques matérielles proches et à des capacités d'optimisation élevées, qui conviennent aux besoins de haute performance tels que le développement de jeux. 2. L'avantage de Golang réside dans sa syntaxe concise et son soutien à la concurrence naturelle, qui convient au développement élevé de services de concurrence.

Golang et C: les compromis en performance Golang et C: les compromis en performance Apr 17, 2025 am 12:18 AM

Les différences de performance entre Golang et C se reflètent principalement dans la gestion de la mémoire, l'optimisation de la compilation et l'efficacité du temps d'exécution. 1) Le mécanisme de collecte des ordures de Golang est pratique mais peut affecter les performances, 2) la gestion manuelle de C et l'optimisation du compilateur sont plus efficaces dans l'informatique récursive.

See all articles