La POO pour les nuls

Informations pour bien débuter en PureBasic
Avatar de l’utilisateur
microdevweb
Messages : 1802
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: La Poo pour les nulles

Message par microdevweb »

Faire une méthodes abstraite

Comme vous devez vous en douter, chaque fois la difficulté monte d'un cran. Mais faire une méthode dite abstraire n'est pas si compliqué.

Une structure peut contenir un peux près tous ce que l'on veux et y compris des pointeurs.

Le pointeur qui pour rappel ne contienne que l'adresse de quelque chose comme une variable ou un procédure, peuvent contenir l'adresse d'une procédure qui peut être prototypée.

Et c'est là que l'on va vraiment pouvoir s'amuser comme des petit fouts :mrgreen: .

Bon pour ceux qui on fait un peu de C, on doit faire des prototypes pour les fonction avant de pouvoir les utilisées. En PureBasic pas et c'est très bien ainsi, par contre on peut créer un prototype pour un pointeur qui pointera lui même sur l'adresse de la fonction.On pourra donc utiliser le dit pointeur comme un appel de procédure standard.

Remarque : fonctionne avec * ou sans

Exemple:

Code : Tout sélectionner

Prototype.s p_bonjour(nom.s)
Prototype.s p_byeBye()
Prototype p_additionne(n1,n2)
Structure teste
  ditBonjour.p_bonjour  ; Remarque : fonctionne avec * ou sans 
  ditByeBye.p_byeBye
  *additionne.p_additionne ; cela aurait fonctionné sans *
EndStructure
Procedure bonjour(nom.s)
  Debug "Bonjour "+nom 
EndProcedure
Procedure hello(nom.s)
  Debug "Hello "+nom 
EndProcedure
Procedure aurevoir()
  Debug "Au revoir et bonne journée"
EndProcedure
Procedure bye()
  Debug "Bye bye have a nice day"
EndProcedure
Procedure additionne(n1,n2)
  Debug Str(n1+n2)
EndProcedure
Define.teste mesMethodes,mesAutreMethode
; je renseignes les adresses des procédure sans paramètre
mesMethodes\ditBonjour = @bonjour()
mesMethodes\ditByeBye = @aurevoir()
mesMethodes\additionne = @additionne()

mesAutreMethode\ditBonjour = @hello()
mesAutreMethode\ditByeBye = @bye()
mesAutreMethode\additionne = @additionne()

; terste
mesMethodes\ditBonjour("Piere")
mesAutreMethode\ditBonjour("Pierre")
mesMethodes\ditByeBye()
mesAutreMethode\ditByeBye()
mesMethodes\additionne(10,8)
mesAutreMethode\additionne(30,60)
Comme vous pouvez le constaté les pointeurs et les prototypes c'est très puissant et offre énormément de possibilités.

Et c'est cette technique que nous allons utilisée pour créer nos méthodes abstraites.

Aller fini la parlote voici comment faire

Code : Tout sélectionner



Prototype p_draw(*this) ; il est indispensable de récupérer l'adresse de l'instance
                        ; pour cette exemple je ne vais pas implémenté les getters et setters


Interface Forme
  draw()
EndInterface
Interface Rectangle Extends forme
  ; vide dans le cadre du tuto
EndInterface
Interface Cercle Extends forme
  ; vide dans le cadre du tuto
EndInterface
; cette classe sera abstraite car elle n'aura pas de constructeur
Structure _forme
  *methods
  x.l
  y.l
  draw.p_draw ; la fameuse méthode abstraite
EndStructure
Structure _rectangle Extends _forme
  w.l
  h.l
EndStructure
Structure _cercle Extends _forme
  r.l
EndStructure
; méthode abstraite de rectangle
Procedure drawRectangle(*this._rectangle)
  With *this
    Debug "Je dessine le rectangle "+Str(\w)+" sur "+Str(\h) 
  EndWith
EndProcedure
; méthode abstraite de cercle
Procedure drawCercle(*this._cercle)
  With *this
    Debug "Je dessine un beau cercle de "+Str(\r)+" de rayon" 
  EndWith
EndProcedure
; méthode abstraite de forme
Procedure draw(*this._forme)
  With *this
    \draw(*this)  ; j'appelle la procédure selon la classe fille
                  ; polymorphisme bricolé :)
  EndWith
EndProcedure
; constructeur de rectangle
Procedure newRectangle(x,y,w,h)
  Protected *this._rectangle = AllocateStructure(_rectangle)
  With *this
    ; comme pour ce tuto il n'y pas de méthodes pour les classes filles
    ; je passe directement les adresses
    \methods = ?S_forme
    \x = x
    \y = y
    \w = w
    \h = h
    \draw = @drawRectangle() ; je renseigne l'adresse de la procédure appropriée
    ProcedureReturn *this
  EndWith
EndProcedure
; constructeur de cercle
Procedure newCercle(x,y,r)
  Protected *this._cercle = AllocateStructure(_cercle)
  With *this
    ; comme pour ce tuto il n'y pas de méthodes pour les classes filles
    ; je passe directement les adresses
    \methods = ?S_forme
    \x = x
    \y = y
    \r = r
    \draw = @drawCercle() ; je renseigne l'adresse de la procédure appropriée
    ProcedureReturn *this
  EndWith
EndProcedure

DataSection
  S_forme:
  Data.i @draw()
EndDataSection

; aller on teste
Define.Forme monRectangle1,monRectangle2,monCercle1,monCercle2

monRectangle1 = newRectangle(10,10,800,200)
monRectangle2 = newRectangle(10,10,400,100)
monCercle1 = newCercle(20,50,60)
monCercle2 = newCercle(20,50,120)

monRectangle1\draw()
monRectangle2\draw()
monCercle1\draw()
monCercle2\draw()

Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
microdevweb
Messages : 1802
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: La POO pour les nuls

Message par microdevweb »

Faire tout un soft en style Poo peut demander beaucoup de travail, donc je viens de démarrer un projet pour faciliter tout cela.

Il sera en deux étapes
  • un model exploitable
  • un interface graphique
Voici le genre de code qu'il faudra taper, et cela créera la structure de toutes les classes dans des fichiers séparé et répertorié.

Code : Tout sélectionner

; *************************************************************************
; AUTHOR          : MicrodevWeb 
; PROJECT NAME    : Poo maker
; PROJECT VERSION : 1.0
; PROJECT DATE    : 2018/09/05        
; DESIGNED WITH   : PB 5.62
; *************************************************************************
IncludePath "Modules/"
XIncludeFile "Model.pbi"
UseModule Model
Global.Project drawingProject = newProject("drawing")
mModel.Package = drawingProject\addPackage(newPackage("Model"))
mForm.AbstractClass = mModel\addClass(newAbstractClass("Form"))
mForm\addMember(newPublicMember("pos_x",#MB_TYPE_INTEGER))
mForm\addMember(newPublicMember("pos_y",#MB_TYPE_INTEGER))

mCircle.PublicClass = mModel\addClass(newPublicClassEtendsOf("cCircle",mForm))
mCircle\addMember(newPublicMember("radius",#MB_TYPE_INTEGER))

mRectangle.PublicClass = mModel\addClass(newPublicClassEtendsOf("Rectangle",mForm))
mRectangle\addMember(newPublicMember("width",#MB_TYPE_INTEGER))
mRectangle\addMember(newPublicMember("heigth",#MB_TYPE_INTEGER))


drawingProject\build("C:\Users\microdevweb\OneDrive\POO_MAKER\Teste")
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Shadow
Messages : 1413
Inscription : mer. 04/nov./2015 17:39

Re: La POO pour les nuls

Message par Shadow »

Salut,

J'ai pas mal chercher pour faire un style de POO avec un style simple, exemple:

MonObjet.X = 45
MonObjet.Detruire()

Ont ne peu pas, donc jme suis dis peut etre ça ?:

MonObjet\X = 45
MonObjet\Detruire()

Possible de le faire oui avec interface mais pas facile.

Et puis moi je voulais séparer les propriété des méthode donc j'ai finie par faire sa avec l'aide de l'IA qui ma aider à améliorer au fil du temps et ma trouver un super truc qui semble bien marcher mais c'est loin d'être parfait mais la syntaxe que je voulais était là elle.

Maintenant sa donne un truc du genre:

MonObjet\Propriétés\X = 45
MonObjet\Methodes\Detruire()

Voici un code d'exemple:

Code : Tout sélectionner

; Code créer par Dieppedalle David avec l'aide de l'IA, le 21/02/2025.
; Code created by Dieppedalle David with the help of AI, on 02/21/2025.

; ======================================================
; Structure des propriétés de l'Objet.
; Structure of the Object's properties.
; ======================================================
Structure ObjectProperties
  ID.i    ; L'ID de l'Objet              |   The ID of the Object.
  Name.s  ; Le nom de l'Objet.           |   The Name of the Object.
  X.i     ; La coordonnée ou valeur X.   |   The X coordinate or value.
  Y.i     ; La coordonnée ou valeur Y.   |   The Y coordinate or value.
EndStructure

; ======================================================
; Prototypes pour les méthodes.
; Prototypes for methods.
; ======================================================
Prototype.i ProtoIntFunc()                             ; Méthode sans paramètre qui retourne un entier.                      |   Method without parameters that returns an integer.
Prototype.s ProtoStrFunc()                             ; Méthode sans paramètre qui retourne une chaîne.                     |   Method without parameters that returns a string.
Prototype.s ProtoStrFuncWithParams(Title.s, Message.s) ; Méthode avec paramètres (Title, Message) qui retourne une chaîne.   |   Method with parameters (Title, Message) that returns a string.

; ======================================================
; Une structure où chaque champ contient l'adresse 
; de la procédure qui porte le nom du champ.
;
; A structure where each field contains the address 
; of the procedure with the same name as the field.
; ======================================================
Structure ObjectMethods
  *Abc123.ProtoIntFunc           ; *Abc123 est un Pointeur de Type ProtoIntFunc qui est un Prototype.             |   *Abc123 is a Pointer of Type ProtoIntFunc which is a Prototype.
  *Abc246.ProtoIntFunc           ; *Abc246 est un Pointeur de Type ProtoIntFunc qui est un Prototype.             |   *Abc246 is a Pointer of Type ProtoIntFunc which is a Prototype.
  *AbcXY.ProtoIntFunc            ; *AbcXY est un Pointeur de Type ProtoIntFunc qui est un Prototype.              |   *AbcXY is a Pointer of Type ProtoIntFunc which is a Prototype.
  *AbcStr.ProtoStrFunc           ; *AbcStr est un Pointeur de Type ProtoStrFunc qui est un Prototype.             |   *AbcStr is a Pointer of Type ProtoStrFunc which is a Prototype.
  *AbcBox.ProtoStrFuncWithParams ; *AbcBox est un Pointeur de Type ProtoStrFuncWithParams qui est un Prototype.   |   *AbcBox is a Pointer of Type ProtoStrFuncWithParams which is a Prototype.
EndStructure

; ======================================================
; Structure principale de l'Objet.
; Main Object structure.
; ======================================================
Structure StructureObject
  *Properties.ObjectProperties  ; Pointeur (*Properties) de type ObjectProperties qui pointe vers les propriétés (état).   |   Pointer (*Properties) of type ObjectProperties that points to properties (state).
  *Methods.ObjectMethods        ; Pointeur (*Methods) de type ObjectMethods qui pointe vers les méthodes (comportement).   |   Pointer (*Methods) of type ObjectMethods that points to methods (behavior).
EndStructure

Global NextObjectID.i = 1
Global *CurrentObject.StructureObject  ; Variable globale pour stocker l'Objet courant.   |   Global variable to store the current Object.

; ======================================================
; Des procédures quelconque.
; Any procedures.
; ======================================================
Procedure.i Abc123()
  ProcedureReturn 123  ; Retourne la valeur entière 123.   |   Returns the integer value 123.
EndProcedure

Procedure.i Abc246()
  ProcedureReturn 246  ; Retourne la valeur entière 246.   |   Returns the integer value 246.
EndProcedure

Procedure.i AbcXY()
  ; Utilise le contexte global pour accéder aux propriétés de l'Objet courant. 
  ; Uses the global context to access the properties of the current Object.
  If *CurrentObject And *CurrentObject\Properties
    ProcedureReturn *CurrentObject\Properties\X + *CurrentObject\Properties\Y
  Else
    Debug "Error: Object Or properties Not initialized."
    ProcedureReturn 0
  EndIf
EndProcedure

Procedure.s AbcStr()
  ; Utilise le contexte global pour accéder aux propriétés de l'Objet courant et retourne une chaîne formatée. 
  ; Uses the global context to access the properties of the current Object and returns a formatted string.
  If *CurrentObject And *CurrentObject\Properties
    ProcedureReturn "X + Y = " + Str(*CurrentObject\Properties\X + *CurrentObject\Properties\Y)
  Else
    Debug "Error: Object Or properties Not initialized."
    ProcedureReturn ""
  EndIf
EndProcedure

Procedure.s AbcBox(Title.s, Message.s)
  ; Affiche une boîte de message avec un titre et un message, puis retourne une chaîne de confirmation.
  ; Displays a message box with a title and message, then returns a confirmation string.
  MessageRequester(Title, Message)
  ProcedureReturn "Message displayed !"
EndProcedure

; ======================================================
; Création d'un nouvel Objet.
; Creating a new Object.
; ======================================================
Procedure.i NewObject()
  
  ; Déclare un Pointeur (*Object) protégé de type StructureObject, qui prend comme valeur l'adresse de la structure "StructureObject".
  ; Ensuite, alloue un nouvel Objet de type Structure dynamique.
  ; 
  ; Declares a protected Pointer (*Object) of type StructureObject, which takes as a value the address of the "StructureObject" structure.
  ; Then, allocates a new Object of dynamic Structure type.
  Protected *Object.StructureObject = AllocateStructure(StructureObject)
  
  ; Si l'Objet *Object est bien initialisé.
  ; If the Object *Object is properly initialized.
  If *Object.StructureObject
    
    ; Alloue un nouvel Objet "Properties" de type Structure dynamique qui prend comme valeur l'adresse de la structure "ObjectProperties".
    ; Allocates a new "Properties" Object of dynamic Structure type which takes as a value the address of the "ObjectProperties" structure.
    *Object\Properties = AllocateStructure(ObjectProperties)
    
    ; Si l'Objet "Properties" n'est pas initialisé.
    ; If the "Properties" Object is not initialized.
    If Not *Object\Properties
      Debug "Error: Unable To allocate Object properties."
      FreeStructure(*Object) ; Supprime l'Objet car il a pu être créé.   |   Remove the Object as it has been created.
      ProcedureReturn 0
    EndIf
    
    ; Alloue un nouvel Objet "Methods" de type Structure dynamique qui prend comme valeur l'adresse de la structure "ObjectMethods".
    ; Allocates a new "Methods" Object of dynamic Structure type which takes as a value the address of the "ObjectMethods" structure.
    *Object\Methods = AllocateStructure(ObjectMethods)
    
    ; Si l'Objet "Methods" n'est pas initialisé.
    ; If the "Methods" Object is not initialized.
    If Not *Object\Methods
      Debug "Error: Unable To allocate Object methods."
      FreeStructure(*Object\Properties) ; Supprime les propriétés de l'Objet car elles ont pu être créées.   |   Remove the properties of the Object as they have been created.
      FreeStructure(*Object)            ; Supprime l'Objet car il a pu être créé.   |   Remove the Object as it has been created.
      ProcedureReturn 0
    EndIf
    
    ; Affecte un Numéro d'identification à l'Objets en fonction de la variable NextObjectID.i.
    ; Assigns an identification number to the object according to the NextObjectID.i variable.
    *Object\Properties\ID = NextObjectID.i
    NextObjectID.i + 1
    
    ; Associe les méthodes aux champs correspondants, chaque champ contient l'adresse mémoire de la procédure qui porte le nom du champ.
    ; Associates methods with the corresponding fields, each field contains the memory address of the procedure that has the same name as the field.
    *Object\Methods\Abc123 = @Abc123()
    *Object\Methods\Abc246 = @Abc246()
    *Object\Methods\AbcXY = @AbcXY()
    *Object\Methods\AbcStr = @AbcStr()
    *Object\Methods\AbcBox = @AbcBox()
    
    ; Retourne un pointeur qui est l'adresse mémoire de la structure "StructureObject".
    ; Returns a pointer which is the memory address of the "StructureObject" structure.
    ProcedureReturn *Object
    
  Else
    ProcedureReturn 0
    
  EndIf

EndProcedure

; ======================================================
; Détruit un objet et libère toute sa mémoire allouée.
; Destroys an Object and releases all its allocated memory.
; ======================================================
Procedure.b DestroyObject(*Object.StructureObject)
  
  ; Vérifie si l'objet est valide (non-nul)   |   Checks if Object is valid (non-null).
  If *Object
    
    If *Object\Properties 
      FreeStructure(*Object\Properties) ; Libère les propriétés   |   Frees properties.
    EndIf
    
    If *Object\Methods 
      FreeStructure(*Object\Methods) ; Libère les méthodes   |   Frees methods.
    EndIf
    
    FreeStructure(*Object) ; Libère l'objet principal   |   Frees main Object.
    
    ProcedureReturn 1
    
  Else
    Debug "Error: Object Not initialized: " + Str(*Object)
    ProcedureReturn 0
    
  EndIf
    
EndProcedure




; --------------------------------

; Exemple d'utilisation:
; Example of use:

; ======================================================
; Création d'instance.
; Instance creation.
; ======================================================
*MyObject.StructureObject = NewObject() ; Crée un nouvel Objet.   |   Creates a new Object.

; Si l'Objet existe.   |   If the Object exists.
If *MyObject
  
; *CurrentObject est un Pointeur globale définie plus haut dans le code qui sert à savoir l'Objet courant actuel.
; *CurrentObject is a Global Pointer defined earlier in the code, used to identify the current Object.
*CurrentObject = *MyObject ; Enregistre l'Objet courant (*MyObject) dans le pointeur *CurrentObject, sert à ne pas passer l'Objet *MyObject en paramètre des méthodes.
                           ; Saves the current Object (*MyObject) in the *CurrentObject pointer, so as not to pass the *MyObject as a methods parameter.

Debug "Adress Object: " + Str(*MyObject)                       ; Affiche l'adresse mémoire de l'instance de l'Objet.         |   Displays the memory address of the Object instance.
Debug "Adress Object Properties: " + Str(*MyObject\Properties) ; Affiche l'adresse mémoire de la structure des propriétés.   |   Displays the memory address of the properties structure.
Debug "Adress Object Methods: " + Str(*MyObject\Methods)       ; Affiche l'adresse mémoire de la structure des méthodes.     |   Displays the memory address of the methods structure.
Debug "-----------------------------------"

; ======================================================
; Modification des propriétés.
; Modification of properties.
; ======================================================
*MyObject\Properties\Name = "Object #1"    ; Définit la propriété Name à "Object #1".    |   Sets Name property to "Object #1".
*MyObject\Properties\X = 15                ; Définit la propriété X à la valeur de 15.   |   Sets X property to 15.
*MyObject\Properties\Y = 25                ; Définit la propriété Y à la valeur de 25.   |   Sets Y property to 25.

Debug "Object ID: " + Str(*MyObject\Properties\ID)  ; Affiche la valeur de la propriété ID.                          |   Displays ID property value.
Debug "Object X: " + Str(*MyObject\Properties\X)    ; Affiche la valeur de la propriété X.                           |   Displays X property value.
Debug "Object Y: " + Str(*MyObject\Properties\Y)    ; Affiche la valeur de la propriété Y.                           |   Displays Y property value.
Debug "Object Name: " + *MyObject\Properties\Name   ; Affiche la valeur de la propriété Name sous forme de chaîne.   |   Displays Name property value as a string.
Debug "-----------------------------------"

; ======================================================
; Appel des fonctions sans passer explicitement les propriétés dans les paramètres. 
; Calling functions without explicitly passing properties in parameters. 
; ======================================================
Debug "Adress Object Methode Abc123:" + Str(*MyObject\Methods\Abc123)    ; Affiche l'adresse mémoire de la méthode Abc123().   |    Displays memory address of Abc123 method().
Debug "Adress Object Methode Abc246:" + Str(*MyObject\Methods\Abc246)    ; Affiche l'adresse mémoire de la méthode Abc246().   |    Displays memory address of Abc246 method().
Debug "Adress Object Methode AbcXY:" + Str(*MyObject\Methods\AbcXY)      ; Affiche l'adresse mémoire de la méthode AbcXY().    |    Displays memory address of AbcXY method().
Debug "Adress Object Methode AbcStr:" + Str(*MyObject\Methods\AbcStr)    ; Affiche l'adresse mémoire de la méthode AbcStr().   |    Displays memory address of AbcStr method().
Debug "Adress Object Methode AbcBox:" + Str(*MyObject\Methods\AbcBox)    ; Affiche l'adresse mémoire de la méthode AbcBox().   |    Displays memory address of AbcBox method().
Debug "-----------------------------------"

Debug "Object Fonction Abc123: " + Str(*MyObject\Methods\Abc123())       ; Appelle et affiche le résultat de la méthode Abc123().   |    Calls and displays result from Abc123 method().
Debug "Object Fonction Abc246: " + Str(*MyObject\Methods\Abc246())       ; Appelle et affiche le résultat de la méthode Abc246().   |    Calls and displays result from Abc246 method().
Debug "Object Fonction AbcXY: " + Str(*MyObject\Methods\AbcXY())         ; Appelle et affiche le résultat de la méthode AbcXY().    |    Calls and displays result from AbcXY method().
Debug "Object Fonction AbcStr: " + *MyObject\Methods\AbcStr()            ; Appelle et affiche le résultat de la méthode AbcStr().   |    Calls and displays result from AbcStr method().

; Appel de la méthode avec paramètres:   -   Calling a method with parameters:
Debug "Result of AbcBox: " + *MyObject\Methods\AbcBox("Information", "Hello, world!")

Else
  Debug "Erreur: Objet non initialisés: " + Str(*MyObject)
  
EndIf
Dernière modification par Shadow le sam. 22/févr./2025 17:21, modifié 1 fois.
Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.
Shadow
Messages : 1413
Inscription : mer. 04/nov./2015 17:39

Re: La POO pour les nuls

Message par Shadow »

Dans mon code, voici une allégorie de ce qu'il fait (Texte créer par IA, modifier un peu par moi):

*1. MyObject: Le "maître" invisible !

Rôle: Il coordonne ses deux employés (Properties et Methods) sans jamais interagir directement avec le monde extérieur.
Pouvoir: Il embauche et licencie ses employés grâce à (NewObject() et FreeStructure()).
Limite: Il ne voit que ses employés (Properties et Methods), pas les sous-traitants (X, Y, Name, AbcXY...).

**2. Les employés: Properties et Methods

*Properties (Service des Données)
Rôle: Gère les sous-traitants: X, Y, Name.
Actions: Transmet et recueille des données de la par de ces
Secret: Les les sous-traitants Ignore totalement l'existence de *MyObject et vice et versa.

*Methods (Service des Opérations)
Rôle: Engage des experts externes (AbcXY, AbcStr...) pour effectuer des tâches.
Actions: Donnes des ordres
Secret: Les experts ne savent pas qu'ils travaillent pour *MyObject et vice et versa.

3. Les sous-traitants : X, Y, Name, AbcXY...
Statut: Indépendants, interchangeables, spécialisés.

Relation:

X/Y/Name : Ne connaissent que *Properties.
AbcXY/AbcStr: Ne connaissent que *Methods.

Ignorance mutuelle: Aucun sous-traitant ne sait que *MyObject existe.

4. Contrôle pyramidal: Le génie de l'architecture
Niveau 1: *MyObject (PDG)
Niveau 2: *Properties (Directeur Data) et *Methods (Directeur Opérations)
Niveau 3: X/Y/Name (Data) et AbcXY/AbcStr (Opérations)

Avantages:

Encapsulation: Aucune fuite d'information entre niveaux.
Flexibilité: Changer *Properties ou *Methods n'affecte pas *MyObject.
Évolutivité: Ajout facile de nouveaux sous-traitants (ex: Z, AbcLog...).

5. Limite philosophique: L'isolement du maître
*MyObject est un manipulateur omniscient mais isolé:

Il contrôle tout via ses employés qui ne sont que des espèce de facteur, mais lui ne communique jamais directement
avec les sous-traitants de peur de se salir les main et d'avoir des problèmes avec la justice ou son karma.

Les sous-traitants agissent en aveugles, sans savoir qui les mandate, ce ne sont que des pions.
C'est le prix de l'abstraction : *MyObject sacrifie sa "visibilité" pour gagner en pouvoir organisationnel.
Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.
Shadow
Messages : 1413
Inscription : mer. 04/nov./2015 17:39

Re: La POO pour les nuls

Message par Shadow »

Salut, voici une deuxième approche, mieux selon moi car pas besoin notamment du pointeur courant de l'objet (Surement boger):

Code : Tout sélectionner

; Code créer par Dieppedalle David avec l'aide de l'IA, le 22/02/2025.
; Code created by Dieppedalle David with the help of AI, on 22/02/2025.

; ======================================================
; Structure des propriétés de l'Objet.
; Structure of the Object's properties.
; ======================================================
Structure ObjectProperties
  ID.i    ; L'ID de l'Objet              |   The ID of the Object.
  Name.s  ; Le nom de l'Objet.           |   The Name of the Object.
  X.i     ; La coordonnée ou valeur X.   |   The X coordinate or value.
  Y.i     ; La coordonnée ou valeur Y.   |   The Y coordinate or value.
EndStructure

; ======================================================
; Interface pour les méthodes de l'Objet.
; Interface for Object methods.
; ======================================================
Interface ObjectMethods ; Les Noms des procédures doivent être identiques à ceux du code, avec les mêmes types et les mêmes paramètres.
                        ; The names of the procedures must be identical to those in the code, with the same types and the same parameters.
  Abc123.i()
  Abc246.i()
  AbcXY.i()
  AbcStr.s()
  AbcBox.s(Title.s, Message.s)
  
EndInterface

; ======================================================
; Structure principale de l'Objet.
; Main Object structure.
; ======================================================
Structure StructureObject
  *VirtualTableObject           ; Pointeur (*VirtualTableObject) sans type, qui pointe vers l'adresse des procedures.      |   Pointer (*VirtualTableObject) without type, which points to the address of the procedures.
  *Properties.ObjectProperties  ; Pointeur (*Properties) de type ObjectProperties qui pointe vers les propriétés (état).   |   Pointer (*Properties) of type ObjectProperties that points to properties (state).
  *Methods.ObjectMethods        ; Pointeur (*Methods) de type ObjectMethods qui pointe vers les méthodes (comportement).   |   Pointer (*Methods) of type ObjectMethods that points to methods (behavior).
EndStructure

Global NextObjectID.i = 1

; ======================================================
; Des procédures quelconque.
; Any procedures.
; ======================================================
Procedure.i Abc123(*Object.StructureObject)
  ProcedureReturn 123  ; Retourne la valeur entière 123.   |   Returns the integer value 123.
EndProcedure

Procedure.i Abc246(*Object.StructureObject)
  ProcedureReturn 246  ; Retourne la valeur entière 246.   |   Returns the integer value 246.
EndProcedure

Procedure.i AbcXY(*Object.StructureObject)
  ; Si l'Objet est valide.   |    If the Object is valid.
  If *Object
    ProcedureReturn *Object\Properties\X + *Object\Properties\Y
  Else
    Debug "Error: Object Or properties Not initialized."
    ProcedureReturn 0
  EndIf
EndProcedure

Procedure.s AbcStr(*Object.StructureObject)
  ; Si l'Objet est valide.   |    If the Object is valid.
  If *Object
    ProcedureReturn "X + Y = " + Str(*Object\Properties\X + *Object\Properties\Y)
  Else
    Debug "Error: Object Or properties Not initialized."
    ProcedureReturn ""
  EndIf
EndProcedure

Procedure.s AbcBox(*Object.StructureObject, Title.s, Message.s)
  ; Affiche une boîte de message avec un titre et un message, puis retourne une chaîne de confirmation.
  ; Displays a message box with a title and message, then returns a confirmation string.
  MessageRequester(Title, Message)
  ProcedureReturn "Message displayed !"
EndProcedure

; Création de la table virtuel, elle sert à stocker les adresses des procédures (Médhodes).
; Create virtual table, It is used to store procedure addresses (Medhodes).
DataSection
  VirtualTableObject:
  Data.i @Abc123()
  Data.i @Abc246()
  Data.i @AbcXY()
  Data.i @AbcStr()
  Data.i @AbcBox()
EndDataSection

; ======================================================
; Création d'un nouvel Objet.
; Creating a new Object.
; ======================================================
Procedure.i NewObject()
  
  ; Déclare un Pointeur (*Object) protégé de type StructureObject, qui prend comme valeur l'adresse de la structure "StructureObject".
  ; Ensuite, alloue un nouvel Objet de type Structure dynamique.
  ; 
  ; Declares a protected Pointer (*Object) of type StructureObject, which takes as a value the address of the "StructureObject" structure.
  ; Then, allocates a new Object of dynamic Structure type.
  Protected *Object.StructureObject = AllocateStructure(StructureObject)
  
  ; Si l'Objet *Object est bien initialisé.
  ; If the Object *Object is properly initialized.
  If *Object.StructureObject
    
    *Object\VirtualTableObject = ?VirtualTableObject
    
    ; Alloue un nouvel Objet "Properties" de type Structure dynamique qui prend comme valeur l'adresse de la structure "ObjectProperties".
    ; Allocates a new "Properties" Object of dynamic Structure type which takes as a value the address of the "ObjectProperties" structure.
    *Object\Properties = AllocateStructure(ObjectProperties)
    
    ; Si l'Objet "Properties" n'est pas initialisé.
    ; If the "Properties" Object is not initialized.
    If Not *Object\Properties
      Debug "Error: Unable To allocate Object properties."
      FreeStructure(*Object) ; Supprime l'Objet car il a pu être créé.   |   Remove the Object as it has been created.
      ProcedureReturn 0
    EndIf
    
    ; Affecte un Numéro d'identification à l'Objets en fonction de la variable NextObjectID.i.
    ; Assigns an identification number to the object according to the NextObjectID.i variable.
    *Object\Properties\ID = NextObjectID.i
    NextObjectID.i + 1
    
    ; Alloue un nouvel Objet "Methods" de type Structure dynamique qui prend comme valeur l'adresse de la structure "ObjectMethods".
    ; Allocates a new "Methods" Object of dynamic Structure type which takes as a value the address of the "ObjectMethods" structure.
    *Object\Methods = AllocateStructure(ObjectMethods)
    
    ; Si l'Objet "Methods" n'est pas initialisé.
    ; If the "Methods" Object is not initialized.
    If Not *Object\Methods
      Debug "Error: Unable To allocate Object methods."
      FreeStructure(*Object\Properties) ; Supprime les propriétés de l'Objet car elles ont pu être créées.   |   Remove the properties of the Object as they have been created.
      FreeStructure(*Object)            ; Supprime l'Objet car il a pu être créé.   |   Remove the Object as it has been created.
      ProcedureReturn 0
    EndIf
    
    ; Methods reçois la structure de l'Objet ou la Table Virtuel est stocké pour réfférencer les Procédures.
    ; Methods receives the structure of the Object where the Virtual Table is stored to refferentiate the Procedures.
    *Object\Methods = *Object 
    
    ; Retourne un pointeur qui est l'adresse mémoire de la structure "StructureObject".
    ; Returns a pointer which is the memory address of the "StructureObject" structure.
    ProcedureReturn *Object
    
  Else
    ProcedureReturn 0
    
  EndIf
  
EndProcedure


; ======================================================
; Détruit un objet et libère toute sa mémoire allouée.
; Destroys an Object and releases all its allocated memory.
; ======================================================
Procedure.b DeleteObject(*Object.StructureObject)
  
  ; Vérifie si l'objet est valide (non-nul)   |   Checks if Object is valid (non-null).
  If *Object.StructureObject
    
    If *Object\Properties 
      
      FreeStructure(*Object\Properties) ; Libère les propriétés   |   Frees properties.
      *Object\Properties = 0
      
      If *Object\Methods 
        
        FreeStructure(*Object\Methods) ; Libère les méthodes   |   Frees methods.
        *Object\Methods = 0
        
        *Object.StructureObject = 0
        ProcedureReturn 1
        
      EndIf
      
    EndIf
    
    ProcedureReturn 0
    
  Else
    Debug "Error: Object Not initialized: " + Str(*Object)
    ProcedureReturn 0
    
  EndIf
  
EndProcedure

; --------------------------------

; Exemple d'utilisation:
; Example of use:

; ======================================================
; Création d'instance.
; Instance creation.
; ======================================================
*MyObject.StructureObject = NewObject() ; Crée un nouvel Objet.   |   Creates a new Object.

; Si l'Objet existe.   |   If the Object exists.
If *MyObject
  
  Debug "Adress Object: " + Str(*MyObject)                       ; Affiche l'adresse mémoire de l'instance de l'Objet.         |   Displays the memory address of the Object instance.
  Debug "Adress Object Properties: " + Str(*MyObject\Properties) ; Affiche l'adresse mémoire de la structure des propriétés.   |   Displays the memory address of the properties structure.
  Debug "Adress Object Methods: " + Str(*MyObject\Methods)       ; Affiche l'adresse mémoire de la structure des méthodes.     |   Displays the memory address of the methods structure.
  Debug "-----------------------------------"
  
  ; ======================================================
  ; Modification des propriétés.
  ; Modification of properties.
  ; ======================================================
  *MyObject\Properties\Name = "Object #1"    ; Définit la propriété Name à "Object #1".    |   Sets Name property to "Object #1".
  *MyObject\Properties\X = 15                ; Définit la propriété X à la valeur de 15.   |   Sets X property to 15.
  *MyObject\Properties\Y = 25                ; Définit la propriété Y à la valeur de 25.   |   Sets Y property to 25.
  
  Debug "Object ID: " + Str(*MyObject\Properties\ID)  ; Affiche la valeur de la propriété ID.                          |   Displays ID property value.
  Debug "Object X: " + Str(*MyObject\Properties\X)    ; Affiche la valeur de la propriété X.                           |   Displays X property value.
  Debug "Object Y: " + Str(*MyObject\Properties\Y)    ; Affiche la valeur de la propriété Y.                           |   Displays Y property value.
  Debug "Object Name: " + *MyObject\Properties\Name   ; Affiche la valeur de la propriété Name sous forme de chaîne.   |   Displays Name property value as a string.
  Debug "-----------------------------------"
  
  Debug "Object Fonction Abc123: " + Str(*MyObject\Methods\Abc123())       ; Appelle et affiche le résultat de la méthode Abc123().   |    Calls and displays result from Abc123 method().
  Debug "Object Fonction Abc246: " + Str(*MyObject\Methods\Abc246())       ; Appelle et affiche le résultat de la méthode Abc246().   |    Calls and displays result from Abc246 method().
  Debug "Object Fonction AbcXY: " + Str(*MyObject\Methods\AbcXY())         ; Appelle et affiche le résultat de la méthode AbcXY().    |    Calls and displays result from AbcXY method().
  Debug "Object Fonction AbcStr: " + *MyObject\Methods\AbcStr()            ; Appelle et affiche le résultat de la méthode AbcStr().   |    Calls and displays result from AbcStr method().
  
  ; Appel de la méthode avec paramètres:   -   Calling a method with parameters:
  Debug "Result of AbcBox: " + *MyObject\Methods\AbcBox("Information", "Hello, world!")
  
  ; Pour supprimer un objet, suivez scrupuleusement cette méthode !
  ; To delete an object, follow this method carefully !
  If DeleteObject(*MyObject)
    *MyObject = #NUL
    Debug "Object deleted !" 
  EndIf
  
Else
  Debug "Error: Uninitialized objects: " + Str(*MyObject)
  
EndIf
Dernière modification par Shadow le mar. 25/févr./2025 4:33, modifié 2 fois.
Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.
Shadow
Messages : 1413
Inscription : mer. 04/nov./2015 17:39

Re: La POO pour les nuls

Message par Shadow »

Deux autres exemple créer par l'IA, parfois elle fais des truc vraiment pas mal:

Code : Tout sélectionner

; -------------------------------
; Interface des méthodes
; -------------------------------
Interface ObjectInterface
    Perimeter.i()
    Surface.i()
    Volume.i()
    SetLength(Value.i)
    SetWidth(Value.i)
    SetHeight(Value.i)
    Destroy()
EndInterface

; -------------------------------
; Structure unique optimisée
; -------------------------------
Structure ObjectHandle
    *VirtualTable       ; Champ *VirtualTable obligatoire en première position
    *Methods.ObjectInterface ; Interface des méthodes
    X.i
    Y.i
    Width.i
    Height.i
    Length.i
EndStructure

; -------------------------------
; Implémentation des méthodes
; -------------------------------
Procedure.i Perimeter(*Object.ObjectHandle)
    If *Object = #Null
        ProcedureReturn 0
    EndIf
    ProcedureReturn (*Object\Length + *Object\Width) * 2
EndProcedure

Procedure.i Surface(*Object.ObjectHandle)
    If *Object = #Null
        ProcedureReturn 0
    EndIf
    ProcedureReturn *Object\Length * *Object\Width
EndProcedure

Procedure.i Volume(*Object.ObjectHandle)
    If *Object = #Null
        ProcedureReturn 0
    EndIf
    ProcedureReturn *Object\Length * *Object\Width * *Object\Height
EndProcedure

Procedure SetLength(*Object.ObjectHandle, Value.i)
    If *Object = #Null
        ProcedureReturn
    EndIf
    *Object\Length = Value
EndProcedure

Procedure SetWidth(*Object.ObjectHandle, Value.i)
    If *Object = #Null
        ProcedureReturn
    EndIf
    *Object\Width = Value
EndProcedure

Procedure SetHeight(*Object.ObjectHandle, Value.i)
    If *Object = #Null
        ProcedureReturn
    EndIf
    *Object\Height = Value
EndProcedure

Procedure Destroy(*Object.ObjectHandle)
    If *Object = #Null
        FreeStructure(*Object)
        *Object = #Null ; Réinitialisation cruciale
    EndIf
    ProcedureReturn #Null
EndProcedure


; -------------------------------
; Table des méthodes (vTable)
; -------------------------------
DataSection
    ObjectVirtualTable:
    Data.i @Perimeter()
    Data.i @Surface()
    Data.i @Volume()
    Data.i @SetLength()
    Data.i @SetWidth()
    Data.i @SetHeight()
    Data.i @Destroy()
EndDataSection

; -------------------------------
; Factory hyper-optimisée
; -------------------------------
Procedure.i NewObject(Width.i = 10, Height.i = 10, Length.i = 25)
  
  Protected *ObjectHandle.ObjectHandle = AllocateStructure(ObjectHandle)
  
    *ObjectHandle\VirtualTable = ?ObjectVirtualTable
    *ObjectHandle\Methods = *ObjectHandle
    
    ; Initialisation directe
    *ObjectHandle\X = 0
    *ObjectHandle\Y = 0
    *ObjectHandle\Width = Width
    *ObjectHandle\Height = Height
    *ObjectHandle\Length = Length
    
    ProcedureReturn *ObjectHandle
    
EndProcedure

; -------------------------------
; Utilisation ULTIME
; -------------------------------
*MyObject.ObjectHandle = NewObject(10, 20, 45)

; Accès aux méthodes
Debug "=== Méthodes ==="
Debug "Périmètre : " + *MyObject\Methods\Perimeter() ; (45+10)*2 = 110
Debug "Surface : " + *MyObject\Methods\Surface()     ; 45*10 = 450
Debug "Volume : " + *MyObject\Methods\Volume()       ; 45*10*20 = 9000

; Accès direct aux champs (plus de Properties séparé)
Debug Chr(10) + "=== Champs ==="
*MyObject\X = 45
*MyObject\Y = 32
*MyObject\Width = 25
*MyObject\Height = 50
*MyObject\Length = 200

Debug "X: " + *MyObject\X
Debug "Y: " + *MyObject\Y
Debug "Width: " + *MyObject\Width
Debug "Height: " + *MyObject\Height
Debug "Length: " + *MyObject\Length

; Modification via méthodes
Debug Chr(10) + "=== Modification ==="
*MyObject\Methods\SetLength(40)
*MyObject\Methods\SetWidth(30)
*MyObject\Methods\SetHeight(60)

Debug "Nouveau périmètre: " + *MyObject\Methods\Perimeter() ; (40+30)*2 = 140
Debug "Nouvelle Surface: " + *MyObject\Methods\Surface()  ; 40*30 = 1200
Debug "Nouveau volume : " + *MyObject\Methods\Volume()   ; 40*30*60 = 72000

; Nettoyage sécurisé
*MyObject = *MyObject\Methods\Destroy()

; Vérification de la destruction
If *MyObject = #Null
    Debug Chr(10) + "Objet correctement détruit !"
Else
    Debug Chr(10) + "Erreur de destruction !"
EndIf

Code : Tout sélectionner

; -------------------------------
; Interface pour les méthodes
; -------------------------------
Interface ObjectInterface
    Perimeter.i()
    Surface.i()
    Volume.i()
    SetLength(Value.i)
    SetWidth(Value.i)
    SetHeight(Value.i)
    Destroy()
EndInterface

; -------------------------------
; Nouvelles structures optimisées
; -------------------------------
Structure ObjectProperties
    X.i
    Y.i
    Width.i
    Height.i
    Length.i
EndStructure

Structure ObjectHandle
    *VirtualTable       ; Premier champ obligatoire
    *Methods.ObjectInterface
    Properties.ObjectProperties
EndStructure

; -------------------------------
; Implémentation des méthodes (reliées directement au handle)
; -------------------------------
Procedure.i Perimeter(*Object.ObjectHandle)
    If *Object = #Null Or *Object\Properties = #Null
        ProcedureReturn 0 ; Valeur sécurisée
    EndIf
    ProcedureReturn (*Object\Properties\Length + *Object\Properties\Width) * 2
EndProcedure

Procedure.i Surface(*Object.ObjectHandle)
    If *Object = #Null Or *Object\Properties = #Null
        ProcedureReturn 0
    EndIf
    ProcedureReturn *Object\Properties\Length * *Object\Properties\Width
EndProcedure

Procedure.i Volume(*Object.ObjectHandle)
    If *Object = #Null Or *Object\Properties = #Null
        ProcedureReturn 0
    EndIf
    ProcedureReturn *Object\Properties\Length * *Object\Properties\Width * *Object\Properties\Height
EndProcedure

Procedure SetLength(*Object.ObjectHandle, Value.i)
    If *Object = #Null Or *Object\Properties = #Null
        ProcedureReturn
    EndIf
    *Object\Properties\Length = Value
EndProcedure

Procedure SetWidth(*Object.ObjectHandle, Value.i)
    If *Object = #Null Or *Object\Properties = #Null
        ProcedureReturn
    EndIf
    *Object\Properties\Width = Value
EndProcedure

Procedure SetHeight(*Object.ObjectHandle, Value.i)
    If *Object = #Null Or *Object\Properties = #Null
        ProcedureReturn
    EndIf
    *Object\Properties\Height = Value
EndProcedure


Procedure Destroy(*Object.ObjectHandle)
    If *Object = #Null Or *Object\Properties = #Null
        FreeStructure(*Object)
        *Object = #Null ; Réinitialisation cruciale
    EndIf
    ProcedureReturn #Null
EndProcedure

; -------------------------------
; Table des méthodes (VirtualTable)
; -------------------------------
DataSection
    ObjectVirtualTable:
    Data.i @Perimeter()
    Data.i @Surface()
    Data.i @Volume()
    Data.i @SetLength()
    Data.i @SetWidth()
    Data.i @SetHeight()
    Data.i @Destroy()
EndDataSection

; -------------------------------
; Factory simplifiée
; -------------------------------
Procedure.i NewObject(Width.i = 10, Height.i = 10, Length.i = 25)
  
  Protected *ObjectHandle.ObjectHandle = AllocateStructure(ObjectHandle)
  
    *ObjectHandle\VirtualTable = ?ObjectVirtualTable
    *ObjectHandle\Methods = *ObjectHandle ; Auto-référencement
    
    ; Initialisation directe des propriétés
    *ObjectHandle\Properties\X = 0
    *ObjectHandle\Properties\Y = 0
    *ObjectHandle\Properties\Width = Width
    *ObjectHandle\Properties\Height = Height
    *ObjectHandle\Properties\Length = Length
    
    ProcedureReturn *ObjectHandle
EndProcedure


; -------------------------------
; Utilisation COMPLÈTE
; -------------------------------
*MyObject.ObjectHandle = NewObject(10, 20, 45)

; Accès aux méthodes
Debug "=== Méthodes ==="
Debug "Périmètre : " + *MyObject\Methods\Perimeter() ; (45+10)*2 = 110
Debug "Surface : " + *MyObject\Methods\Surface()    ; 45*10 = 450
Debug "Volume : " + *MyObject\Methods\Volume()       ; 45*10*20 = 9000

; Accès direct aux propriétés
Debug Chr(10) + "=== Propriétés ==="
*MyObject\Properties\X = 45
*MyObject\Properties\Y = 32
*MyObject\Properties\Width = 25
*MyObject\Properties\Height = 50
*MyObject\Properties\Length = 200

Debug "X: " + *MyObject\Properties\X
Debug "Y: " + *MyObject\Properties\Y
Debug "Width: " + *MyObject\Properties\Width
Debug "Height: " + *MyObject\Properties\Height
Debug "Length: " + *MyObject\Properties\Length

; Modification via méthodes
Debug Chr(10) + "=== Modification ==="
*MyObject\Methods\SetLength(40)
*MyObject\Methods\SetWidth(30)
*MyObject\Methods\SetHeight(60)

Debug "Nouveau périmètre: " + *MyObject\Methods\Perimeter()
Debug "Nouvelle Surface: " + *MyObject\Methods\Surface()
Debug "Nouveau volume : " + *MyObject\Methods\Volume() ; 40*30*60 = 72000

; Nettoyage
*MyObject = *MyObject\Methods\Destroy()

; Vérification de la destruction
If *MyObject = #Null
  Debug Chr(10) + "Objet correctement détruit !"
Else
  Debug Chr(10) + "Erreur de destruction !"
EndIf
Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.
Avatar de l’utilisateur
Micoute
Messages : 2583
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: La POO pour les nuls

Message par Micoute »

Bonjour Shadow, il faut bien se dire que l'IA va devenir de plus en plus intelligente, mais ne supplantera jamais l'homme puisqu'elle se nourrit de ses écrits, il ne faut pas se mentir, internet est une grande banque de données pour l'IA.
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 6.20 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Shadow
Messages : 1413
Inscription : mer. 04/nov./2015 17:39

Re: La POO pour les nuls

Message par Shadow »

Micoute a écrit : mar. 25/févr./2025 9:22 Bonjour Shadow, il faut bien se dire que l'IA va devenir de plus en plus intelligente, mais ne supplantera jamais l'homme puisqu'elle se nourrit de ses écrits, il ne faut pas se mentir, internet est une grande banque de données pour l'IA.
Salut Micoute,

Je pense que tu te trompe, oui elle va devenir de plus en plus intelligente si on peu dire ça
et si, elle supplantera l'humain, c'est juste une question d'années !

Oui elle se nourrie de tous ce que l'on fait, c'est un aspirateur de savoir.

Pour ce qui est de la POO, la plupart ici ni comprennent rien et j'ai du mal aussi.
Mais pour ceux qui comprenne, dites moi si ce code va ou pas, je l'ai créer avec l'IA.

Sinon concentré vous sur les procédure si vous comprenez rien, dites moi si elle sont correcte.
Si vous avez des idées etc.

Code : Tout sélectionner

; ########################################################
; #                SYSTÈME D'OBJETS HIÉRARCHIQUES        #
; ########################################################

; -------------------------------
; Interface pour les méthodes (déclaration des signatures)
; -------------------------------
Interface ObjectInterface
  AddChild.b(*Child.ObjectHandle)  ; Méthode pour ajouter un enfant
  RemoveChild.b(*Child.ObjectHandle) ; Méthode pour retirer un enfant
EndInterface

; -------------------------------
; Structures de données
; -------------------------------
Structure ObjectProperties ; Propriétés d'un objet
  Name.s                   ; Nom de l'objet
  ID.i                     ; Identifiant unique
  X.i                      ; Position X
  Y.i                      ; Position Y
  Width.i                  ; Largeur
  Height.i                 ; Hauteur
EndStructure

Structure ObjectHandle ; Structure principale d'un objet
  *VirtualTable        ; Table virtuelle pour le polymorphisme
  *Parent.ObjectHandle ; Référence vers l'objet parent
  Map *Children.ObjectHandle() ; Map des enfants (clé = adresse mémoire en string)
  *Methods.ObjectInterface     ; Interface des méthodes
  Properties.ObjectProperties  ; Propriétés de l'objet
EndStructure

Structure ObjectsSystem ; Système global de gestion
  NextID.i              ; Prochain ID auto-incrémenté
EndStructure

; Variable système globale
Global ObjectsSystem.ObjectsSystem

; -------------------------------
; Méthode AddChild (implémentation)
; -------------------------------
Procedure.b AddChild(*Object.ObjectHandle, *Child.ObjectHandle)
  ; Vérification des pointeurs
  If *Object And *Child
    
    ; Suppression de l'ancien parent si existant
    If *Child\Parent
      DeleteMapElement(*Child\Parent\Children(), Str(*Child)) ; Retire de l'ancien parent
    EndIf
    
    ; Mise à jour des références parent/enfant
    *Child\Parent = *Object ; Définit le nouveau parent
    AddMapElement(*Object\Children(), Str(*Child)) ; Ajoute à la map avec clé = adresse
    *Object\Children() = *Child                    ; Stocke le pointeur
    
    ProcedureReturn #True ; Succès
  EndIf
  ProcedureReturn #Null ; Échec
EndProcedure

; -------------------------------
; Méthode RemoveChild (implémentation)
; -------------------------------
Procedure.b RemoveChild(*Object.ObjectHandle, *Child.ObjectHandle)
  ; Vérifications de sécurité
  If *Object And *Child And FindMapElement(*Object\Children(), Str(*Child))
    DeleteMapElement(*Object\Children(), Str(*Child)) ; Retire de la map
    *Child\Parent = #Null                             ; Réinitialise le parent
    
    ProcedureReturn #True ; Succès
  EndIf
  ProcedureReturn #Null ; Échec
EndProcedure

; -------------------------------
; Table des méthodes virtuelles
; -------------------------------
DataSection
  ObjectVirtualTable:
  Data.i @AddChild() ; Entrée 0 : Adresse de AddChild
  Data.i @RemoveChild() ; Entrée 1 : Adresse de RemoveChild
EndDataSection

; -------------------------------
; Constructeur d'objet
; -------------------------------
Procedure.i NewObject()
  ; Aloue de la mémoire (Structure) pour l'objet.
  Protected *ObjectHandle.ObjectHandle = AllocateStructure(ObjectHandle)
  
  If *ObjectHandle
    ; Initialisation des propriétés
    ObjectsSystem\NextID + 1 ; Incrément ID global
    *ObjectHandle\Properties\ID = ObjectsSystem\NextID
    *ObjectHandle\Properties\Name = "Object #" + Str(*ObjectHandle\Properties\ID) ; Nom de l'Objet.
    
    ; Configuration de la table virtuelle
    *ObjectHandle\VirtualTable = ?ObjectVirtualTable ; Pointeur vers la DataSection
    *ObjectHandle\Methods = *ObjectHandle            ; Liaison méthodes
    
    ProcedureReturn *ObjectHandle ; Retourne le nouvel objet
  EndIf
EndProcedure

; -------------------------------
; Destructeur d'objet (récursif)
; -------------------------------
Procedure.b DeleteObject(*Object.ObjectHandle)
  If *Object
    ; Suppression récursive des enfants
    If MapSize(*Object\Children()) > 0
      ForEach *Object\Children()
        DeleteObject(*Object\Children()) ; Appel récursif
      Next
    EndIf
    
    ; Libération de la mémoire
    FreeStructure(*Object) ; Libère la structure et ses maps
    ProcedureReturn #True  ; Succès
  EndIf
  ProcedureReturn #Null ; Échec
EndProcedure

; -------------------------------
; Affichage de la hiérarchie (fonction récursive interne)
; -------------------------------
Procedure PrintHierarchieChild(*ObjectParent.ObjectHandle, Profondeur.i = 0, Tabulation.s = "")
  Protected SubTab.s = Tabulation + Space(10 * (Profondeur + 1))
  Protected ParentName.s = *ObjectParent\Properties\Name
  
  ; Parcours de tous les enfants
  ForEach *ObjectParent\Children()
    Protected *ObjectChild.ObjectHandle = *ObjectParent\Children()
    Protected ChildTab.s = SubTab + "      +- "
    
    ; Affichage formaté des propriétés
    Debug SubTab + "+- Object Chil Name: " + *ObjectChild\Properties\Name + #CRLF$ +
          ChildTab + "Object Chil Parent: " + ParentName + #CRLF$ +
          ChildTab + "Object Chil ID: " + *ObjectChild\Properties\ID + #CRLF$ +
          ChildTab + "Object Chil X: " + *ObjectChild\Properties\X + #CRLF$ +
          ChildTab + "Object Chil Y: " + *ObjectChild\Properties\Y + #CRLF$ +
          ChildTab + "Object Chil Width: " + *ObjectChild\Properties\Width + #CRLF$ +
          ChildTab + "Object Chil Height: " + *ObjectChild\Properties\Height + #CRLF$ +
          ChildTab + "ProfondeurHierarchique: " + Str(Profondeur + 1)
    
    ; Appel récursif pour les sous-enfants
    If MapSize(*ObjectChild\Children()) > 0
      PrintHierarchieChild(*ObjectChild, Profondeur + 1, Tabulation + "  ")
    EndIf
  Next
EndProcedure

; -------------------------------
; Affichage de la hiérarchie racine
; -------------------------------
Procedure PrintHierarchie(*Object.ObjectHandle)
  If Not *Object
    ProcedureReturn 0
  EndIf
  
  ; Affichage de la racine
  Protected RootInfo.s = "      +- "
  Debug "+- Object Name: " + *Object\Properties\Name + #CRLF$ +
        RootInfo + "Object ID: " + *Object\Properties\ID + #CRLF$ +
        RootInfo + "Object X: " + *Object\Properties\X + #CRLF$ +
        RootInfo + "Object Y: " + *Object\Properties\Y + #CRLF$ +
        RootInfo + "Object Width: " + *Object\Properties\Width + #CRLF$ +
        RootInfo + "Object Height: " + *Object\Properties\Height + #CRLF$ +
        RootInfo + "ProfondeurHierarchique: 0"
  
  ; Lancement de l'affichage récursif
  PrintHierarchieChild(*Object, 0, "  ")
EndProcedure

; ########################################################
; #                  EXEMPLE D'UTILISATION               #
; ########################################################

; Création d'un Objet.
Define *MyObjectRootTomas.ObjectHandle = NewObject() ; Tomas - 1

; Définie les Propriétés
*MyObjectRootTomas\Properties\Name = "Tomas" ; Tomas - 1
*MyObjectRootTomas\Properties\X = 45         ; Tomas - 1
*MyObjectRootTomas\Properties\Y = 32         ; Tomas - 1
*MyObjectRootTomas\Properties\Width = 25     ; Tomas - 1
*MyObjectRootTomas\Properties\Height = 50    ; Tomas - 1

; Création d'un Objet.
Define *MyObjectChildMartin.ObjectHandle = NewObject() ; Martin - 2

; Définie les Propriétés
*MyObjectChildMartin\Properties\Name = "Martin" ; Martin - 2
*MyObjectChildMartin\Properties\X = 50          ; Martin - 2
*MyObjectChildMartin\Properties\Y = 35          ; Martin - 2
*MyObjectChildMartin\Properties\Width = 30      ; Martin - 2
*MyObjectChildMartin\Properties\Height = 55     ; Martin - 2

*MyObjectRootTomas\Methods\AddChild(*MyObjectChildMartin) ; Tomas - 1 > Martin - 2

; Création d'un Objet.
Define *MyObjectSubChildLucie.ObjectHandle = NewObject() ; Lucie - 3

; Définie les Propriétés
*MyObjectSubChildLucie\Properties\Name = "Lucie" ; Lucie - 3
*MyObjectSubChildLucie\Properties\X = 55         ; Lucie - 3
*MyObjectSubChildLucie\Properties\Y = 40         ; Lucie - 3
*MyObjectSubChildLucie\Properties\Width = 35     ; Lucie - 3
*MyObjectSubChildLucie\Properties\Height = 60    ; Lucie - 3

*MyObjectChildMartin\Methods\AddChild(*MyObjectSubChildLucie) ; Martin - 2 > Lucie - 3

; Création d'un Objet.
Define *MyObjectSubSubChildLuck.ObjectHandle = NewObject() ; Luck - 4

; Définie les Propriétés
*MyObjectSubSubChildLuck\Properties\Name = "Luck" ; Luck - 4
*MyObjectSubSubChildLuck\Properties\X = 60        ; Luck - 4
*MyObjectSubSubChildLuck\Properties\Y = 45        ; Luck - 4
*MyObjectSubSubChildLuck\Properties\Width = 40    ; Luck - 4
*MyObjectSubSubChildLuck\Properties\Height = 65   ; Luck - 4

*MyObjectSubChildLucie\Methods\AddChild(*MyObjectSubSubChildLuck) ; Lucie - 3 > Luck - 4

; Création d'un Objet.
Define *MyObjectSubSubChildJessica.ObjectHandle = NewObject() ; Jessica - 5

; Définie les Propriétés
*MyObjectSubSubChildJessica\Properties\Name = "Jessica" ; Jessica - 5
*MyObjectSubSubChildJessica\Properties\X = 65           ; Jessica - 5
*MyObjectSubSubChildJessica\Properties\Y = 50           ; Jessica - 5
*MyObjectSubSubChildJessica\Properties\Width = 45       ; Jessica - 5
*MyObjectSubSubChildJessica\Properties\Height = 70      ; Jessica - 5

*MyObjectSubChildLucie\Methods\AddChild(*MyObjectSubSubChildJessica) ; Lucie - 3 > Jessica - 5

; Création d'un Objet.
Define *MyObjectSubChildTome.ObjectHandle = NewObject() ; Tome - 6

; Définie les Propriétés
*MyObjectSubChildTome\Properties\Name = "Tome" ; Tome - 6
*MyObjectSubChildTome\Properties\X = 70        ; Tome - 6
*MyObjectSubChildTome\Properties\Y = 55        ; Tome - 6
*MyObjectSubChildTome\Properties\Width = 50    ; Tome - 6
*MyObjectSubChildTome\Properties\Height = 75   ; Tome - 6

*MyObjectChildMartin\Methods\AddChild(*MyObjectSubChildTome) ; Martin - 2 > Tome - 6

; Création d'un Objet.
Define *MyObjectSubSubSubChildMarine.ObjectHandle = NewObject() ; Marine - 7

; Définie les Propriétés
*MyObjectSubSubSubChildMarine\Properties\Name = "Marine" ; Marine - 7
*MyObjectSubSubSubChildMarine\Properties\X = 75          ; Marine - 7
*MyObjectSubSubSubChildMarine\Properties\Y = 60          ; Marine - 7
*MyObjectSubSubSubChildMarine\Properties\Width = 55      ; Marine - 7
*MyObjectSubSubSubChildMarine\Properties\Height = 80     ; Marine - 7

*MyObjectSubChildTome\Methods\AddChild(*MyObjectSubSubSubChildMarine) ; Tome - 6 > Marine - 7

; Création d'un Objet.
Define *MyObjectChildClaire.ObjectHandle = NewObject() ; Claire - 8

; Définie les Propriétés
*MyObjectChildClaire\Properties\Name = "Claire" ; Claire - 8
*MyObjectChildClaire\Properties\X = 80          ; Claire - 8
*MyObjectChildClaire\Properties\Y = 65          ; Claire - 8
*MyObjectChildClaire\Properties\Width = 60      ; Claire - 8
*MyObjectChildClaire\Properties\Height = 85     ; Claire - 8

*MyObjectRootTomas\Methods\AddChild(*MyObjectChildClaire) ; Tomas - 1 > Claire - 8

; Création d'un Objet.
Define *MyObjectSubChildPaul.ObjectHandle = NewObject() ; Paul - 9

; Définie les Propriétés
*MyObjectSubChildPaul\Properties\Name = "Paul" ; Paul - 9
*MyObjectSubChildPaul\Properties\X = 85        ; Paul - 9
*MyObjectSubChildPaul\Properties\Y = 70        ; Paul - 9
*MyObjectSubChildPaul\Properties\Width = 65    ; Paul - 9
*MyObjectSubChildPaul\Properties\Height = 90   ; Paul - 9

*MyObjectChildClaire\Methods\AddChild(*MyObjectSubChildPaul) ; Claire - 8 > Paul - 9

; Création d'un Objet.
Define *MyObjectSubSubChildLouis.ObjectHandle = NewObject() ; Louis - 10

; Définie les Propriétés
*MyObjectSubSubChildLouis\Properties\Name = "Louis" ; Louis - 10
*MyObjectSubSubChildLouis\Properties\X = 90         ; Louis - 10
*MyObjectSubSubChildLouis\Properties\Y = 75         ; Louis - 10
*MyObjectSubSubChildLouis\Properties\Width = 70     ; Louis - 10
*MyObjectSubSubChildLouis\Properties\Height = 95    ; Louis - 10

*MyObjectSubChildPaul\Methods\AddChild(*MyObjectSubSubChildLouis) ; Paul - 9 > Louis - 10

; Création d'un Objet.
Define *MyObjectSubSubSubChildLea.ObjectHandle = NewObject() ; Lea - 11

; Définie les Propriétés
*MyObjectSubSubSubChildLea\Properties\Name = "Lea" ; Lea - 11
*MyObjectSubSubSubChildLea\Properties\X = 95       ; Lea - 11
*MyObjectSubSubSubChildLea\Properties\Y = 80       ; Lea - 11
*MyObjectSubSubSubChildLea\Properties\Width = 75   ; Lea - 11
*MyObjectSubSubSubChildLea\Properties\Height = 100 ; Lea - 11

*MyObjectSubSubChildLouis\Methods\AddChild(*MyObjectSubSubSubChildLea) ; Louis - 10 > Lea - 11

; Création d'un Objet.
Define *MyObjectSubSubSubChildJules.ObjectHandle = NewObject() ; Jules - 12

; Définie les Propriétés
*MyObjectSubSubSubChildJules\Properties\Name = "Jules" ; Jules - 12
*MyObjectSubSubSubChildJules\Properties\X = 100        ; Jules - 12
*MyObjectSubSubSubChildJules\Properties\Y = 85         ; Jules - 12
*MyObjectSubSubSubChildJules\Properties\Width = 80     ; Jules - 12
*MyObjectSubSubSubChildJules\Properties\Height = 105   ; Jules - 12

*MyObjectSubSubChildLouis\Methods\AddChild(*MyObjectSubSubSubChildJules) ; Louis - 10 > Jules - 12

; Création d'un Objet.
Define *MyObjectSubSubChildEmma.ObjectHandle = NewObject() ; Emma - 13

; Définie les Propriétés
*MyObjectSubSubChildEmma\Properties\Name = "Emma" ; Emma - 13
*MyObjectSubSubChildEmma\Properties\X = 105       ; Emma - 13
*MyObjectSubSubChildEmma\Properties\Y = 90        ; Emma - 13
*MyObjectSubSubChildEmma\Properties\Width = 85    ; Emma - 13
*MyObjectSubSubChildEmma\Properties\Height = 110  ; Emma - 13

*MyObjectSubChildPaul\Methods\AddChild(*MyObjectSubSubChildEmma) ; Paul - 9 > Emma - 13

; Création d'un Objet.
Define *MyObjectSubChildSophie.ObjectHandle = NewObject() ; Sophie - 14

; Définie les Propriétés
*MyObjectSubChildSophie\Properties\Name = "Sophie" ; Sophie - 14
*MyObjectSubChildSophie\Properties\X = 110         ; Sophie - 14
*MyObjectSubChildSophie\Properties\Y = 95          ; Sophie - 14
*MyObjectSubChildSophie\Properties\Width = 90      ; Sophie - 14
*MyObjectSubChildSophie\Properties\Height = 115    ; Sophie - 14

*MyObjectChildClaire\Methods\AddChild(*MyObjectSubChildSophie) ; Claire - 8 > Sophie - 14

; ; Pour visualiser l'arbre généalogique
; Procedure DisplayFamilyTree(*Object.ObjectHandle, Level = 0)
;   Debug (Space(Level * 6) + "+- " + *Object\Properties\Name)
;   ForEach *Object\Children()
;     DisplayFamilyTree(*Object\Children(), Level + 1)
;   Next
; EndProcedure

; DisplayFamilyTree(*MyObjectRootTomas.ObjectHandle, 0)

; +- Tomas
;       +- Claire
;             +- Paul
;                   +- Louis
;                         +- Lea
;                         +- Jules
;                   +- Emma
;             +- Sophie
;       +- Martin
;             +- Lucie
;                   +- Luck
;                   +- Jessica
;             +- Tome
;                   +- Marine
; 

; Affichage de l'arbre complet
PrintHierarchie(*MyObjectRootTomas)

; Nettoyage final
If DeleteObject(*MyObjectRootTomas)
  *MyObjectRootTomas = #Null ; Bonne pratique anti-dangling pointer
  Debug "Nettoyage réussi !"
Else
  Debug "Échec du nettoyage !"
EndIf
Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.
Avatar de l’utilisateur
Micoute
Messages : 2583
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: La POO pour les nuls

Message par Micoute »

Salut Shadow, bien sûr ce code fonctionne très bien.

Je ne mets pas la hiérarchie, car ça ne fonctionne pas avec les éditeurs.
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 6.20 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Avatar de l’utilisateur
falsam
Messages : 7317
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: La POO pour les nuls

Message par falsam »

Shadow a écrit : sam. 01/mars/2025 2:55 Pour ce qui est de la POO, la plupart ici ni comprennent rien
Qu'est ce qui te permet de dire ça ?

Je pense qu'il faut arrêter de vouloir faire de la POO avec un langage qui n'est pas prévu pour cela.

j'ai décrypté et testé ton code. Tu ne fais que compliquer la gestion des structures.

Prenons un exemple de ton code et regarde comment tu assignes tes variables.

Code : Tout sélectionner

; Création d'un Objet.
Define *MyObjectRootTomas.ObjectHandle = NewObject() ; Tomas - 1

; Définie les Propriétés
*MyObjectRootTomas\Properties\Name = "Tomas" ; Tomas - 1
*MyObjectRootTomas\Properties\X = 45         ; Tomas - 1
*MyObjectRootTomas\Properties\Y = 32         ; Tomas - 1
*MyObjectRootTomas\Properties\Width = 25     ; Tomas - 1
*MyObjectRootTomas\Properties\Height = 50    ; Tomas - 1
ce code fait appel à une structure que tu as défini

Code : Tout sélectionner

; -------------------------------
; Structures de données
; -------------------------------
Structure ObjectProperties ; Propriétés d'un objet
  Name.s                   ; Nom de l'objet
  ID.i                     ; Identifiant unique
  X.i                      ; Position X
  Y.i                      ; Position Y
  Width.i                  ; Largeur
  Height.i                 ; Hauteur
EndStructure
Il y avait plus simple pour assigner tes variables ? enfin je crois 🤪

Voici le code.

Code : Tout sélectionner

Define Objet.ObjectProperties

With Objet
  \Name = "Tomas"
  \ID = 45
  \x = 45
  \y = 32
  \Width = 25 
  \Height = 50
EndWith
C'est pas plus simple et facile à lire ? Gloire à PureBasic et vive la simplicité 💕
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
falsam
Messages : 7317
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: La POO pour les nuls

Message par falsam »

Un autre point. Ta gestion des objet ne permet pas d'ajouter des nouvelles propriétés et des types.

Exemple en JavaScript. Je peux définir un objet sans connaitre sa structure. Un exemple simple

Code : Tout sélectionner

let car = new Object();
Je peux maintenant ajouter autant de propriétés que je souhaite.

Code : Tout sélectionner

car.fabricant = "FIAT"
car.model = 500
car.weight = 850
car.color = "White"
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
Mindphazer
Messages : 694
Inscription : mer. 24/août/2005 10:42

Re: La POO pour les nuls

Message par Mindphazer »

falsam a écrit : sam. 01/mars/2025 17:43 Il y avait plus simple pour assigner tes variables ? enfin je crois 🤪
C'est pas plus simple et facile à lire ? Gloire à PureBasic et vive la simplicité 💕
L'art et la manière de se compliquer la vie avec un énorme (et indigeste) plat de spaghettis :mrgreen:
Bureau : Win10 64bits
Maison : Macbook Pro M3 16" SSD 512 Go / Ram 24 Go - iPad Pro 32 Go (pour madame) - iPhone 15 Pro Max 256 Go
Shadow
Messages : 1413
Inscription : mer. 04/nov./2015 17:39

Re: La POO pour les nuls

Message par Shadow »

Falsam, tu n'as pas compris ce que je voulais faire, j'ai peut etre pas expliquer donc c'est normale aussi.
Je veux une syntaxe du style:

Car = CreateCar()

Car.Paint.Color = Red
CarColor = Car.Paint.Color

Car.Engine.Start()
Car.Engine.Stop()

Car = DestroyCar()

Mais nous ne pouvons pas faire cela en PureBasic. Je veux donc créer quelque chose d'aussi proche que possible de cela, et qui soit simple à utiliser. Pour l'instant, je suis satisfait de mon approche car je veux un style bien défini.
Donc je vais faire un truc du genre:

Car = CreateCar()

Car\PaintColor = Red
CarColor = Car\PaintColor

Car\EngineStart()
Car\EngineStop()

Car = DestroyCar()

Vous comprenez maintenant ?

En vraie ce sera un peu différent, ce sera donc un truc comme:
; Création d'un Objet.
*MyObject.ObjectHandle = NewObject()

; Définie les Propriétés:
*MyObject\Properties\Name = "Objet #1"
*MyObject\Properties\X = 50
*MyObject\Properties\Y = 35
*MyObject\Properties\Width = 30
*MyObject\Properties\Height = 55

; Appel d'une méthode:
*MyObject\Methods\AddChild(*MyObject)

DeleteObject(*MyObject)
Car j'ai un projet en tête, mais j'ai déjà parlé de tous ça sur le forum anglais.
Quand ce sera bien au point, je pense que je ferais un générateur de POO...
Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.
Shadow
Messages : 1413
Inscription : mer. 04/nov./2015 17:39

Re: La POO pour les nuls

Message par Shadow »

Actuellement j'en suis ici mais ya surement quelque soucis dans le code bien que sa semble marché:

Code : Tout sélectionner

; ########################################################
; #                SYSTÈME D'OBJETS HIÉRARCHIQUES        #
; ########################################################

DeclareModule VirtualObjectHandlers
  
  ; -------------------------------
  ; Interface pour les méthodes (déclaration des signatures)
  ; -------------------------------
  Interface ObjectInterface
    AddChild.b(*Child.ObjectHandle)  ; Méthode pour ajouter un enfant
    RemoveChild.b(*Child.ObjectHandle) ; Méthode pour retirer un enfant
  EndInterface
  
  ; -------------------------------
  ; Structures de données
  ; -------------------------------
  Structure ObjectProperties ; Propriétés d'un objet
    Name.s                   ; Nom de l'objet
    ID.i                     ; Identifiant unique
    X.i                      ; Position X
    Y.i                      ; Position Y
    Width.i                  ; Largeur
    Height.i                 ; Hauteur
  EndStructure
  
  Structure ObjectHandle ; Structure principale d'un objet
    *VirtualTable        ; Table virtuelle pour le polymorphisme
    *Parent.ObjectHandle ; Référence vers l'objet parent
    Map *Children.ObjectHandle() ; Map des enfants (clé = adresse mémoire en string)
    *Methods.ObjectInterface     ; Interface des méthodes
    Properties.ObjectProperties  ; Propriétés de l'objet
  EndStructure
  
  Declare.i NewObject()
  Declare.b AddChild(*Object.ObjectHandle, *Child.ObjectHandle)
  Declare.b RemoveChild(*Object.ObjectHandle, *Child.ObjectHandle)
  Declare.b DeleteObject(*Object.ObjectHandle)
  
EndDeclareModule

Module VirtualObjectHandlers
  
Structure ObjectsSystem ; Système global de gestion
  NextID.i              ; Prochain ID auto-incrémenté
EndStructure

; Variable système globale
Global ObjectsSystem.ObjectsSystem

; -------------------------------
; Méthode AddChild (implémentation)
; -------------------------------
Procedure.b AddChild(*Object.ObjectHandle, *Child.ObjectHandle)
  ; Vérification des pointeurs
  If *Object And *Child
    
    ; Suppression de l'ancien parent si existant
    If *Child\Parent
      DeleteMapElement(*Child\Parent\Children(), Str(*Child)) ; Retire de l'ancien parent
    EndIf
    
    ; Mise à jour des références parent/enfant
    *Child\Parent = *Object ; Définit le nouveau parent
    AddMapElement(*Object\Children(), Str(*Child)) ; Ajoute à la map avec clé = adresse
    *Object\Children() = *Child                    ; Stocke le pointeur
    
    ProcedureReturn #True ; Succès
  EndIf
  ProcedureReturn #Null ; Échec
EndProcedure

; -------------------------------
; Méthode RemoveChild (implémentation)
; -------------------------------
Procedure.b RemoveChild(*Object.ObjectHandle, *Child.ObjectHandle)
  ; Vérifications de sécurité
  If *Object And *Child And FindMapElement(*Object\Children(), Str(*Child))
    DeleteMapElement(*Object\Children(), Str(*Child)) ; Retire de la map
    *Child\Parent = #Null                             ; Réinitialise le parent
    
    ProcedureReturn #True ; Succès
  EndIf
  ProcedureReturn #Null ; Échec
EndProcedure

; -------------------------------
; Table des méthodes virtuelles
; -------------------------------
DataSection
  ObjectVirtualTable:
  Data.i @AddChild() ; Entrée 0 : Adresse de AddChild
  Data.i @RemoveChild() ; Entrée 1 : Adresse de RemoveChild
EndDataSection

; -------------------------------
; Constructeur d'objet
; -------------------------------
Procedure.i NewObject()
  ; Aloue de la mémoire (Structure) pour l'objet.
  Protected *ObjectHandle.ObjectHandle = AllocateStructure(ObjectHandle)
  
  If *ObjectHandle
    
    ; Initialisation des propriétés
    ObjectsSystem\NextID + 1 ; Incrément ID global
    *ObjectHandle\Properties\ID = ObjectsSystem\NextID
    *ObjectHandle\Properties\Name = "Object #" + Str(*ObjectHandle\Properties\ID) ; Nom de l'Objet.
    
    ; Configuration de la table virtuelle
    *ObjectHandle\VirtualTable = ?ObjectVirtualTable ; Pointeur vers la DataSection
    *ObjectHandle\Methods = *ObjectHandle            ; Liaison méthodes
    
    ProcedureReturn *ObjectHandle ; Retourne le nouvel objet
  EndIf
EndProcedure

; -------------------------------
; Destructeur d'objet (récursif)
; -------------------------------
Procedure.b DeleteObject(*Object.ObjectHandle)
  If *Object
    ; Suppression récursive des enfants
    If MapSize(*Object\Children()) > 0
      ForEach *Object\Children()
        DeleteObject(*Object\Children()) ; Appel récursif
      Next
    EndIf
    
    ; Libération de la mémoire
    FreeStructure(*Object) ; Libère la structure et ses maps
    ProcedureReturn #True  ; Succès
  EndIf
  ProcedureReturn #Null ; Échec
EndProcedure


EndModule




; ########################################################
; #                  EXEMPLE D'UTILISATION               #
; ########################################################

UseModule VirtualObjectHandlers

; -------------------------------
; Affichage de la hiérarchie (fonction récursive interne)
; -------------------------------
Procedure PrintHierarchieChild(*ObjectParent.ObjectHandle, Profondeur.i = 0, Tabulation.s = "")
  Protected SubTab.s = Tabulation + Space(10 * (Profondeur + 1))
  Protected ParentName.s = *ObjectParent\Properties\Name
  
  ; Parcours de tous les enfants
  ForEach *ObjectParent\Children()
    Protected *ObjectChild.ObjectHandle = *ObjectParent\Children()
    Protected ChildTab.s = SubTab + "      +- "
    
    ; Affichage formaté des propriétés
    Debug SubTab + "+- Object Chil Name: " + *ObjectChild\Properties\Name + #CRLF$ +
          ChildTab + "Object Chil Parent: " + ParentName + #CRLF$ +
          ChildTab + "Object Chil ID: " + *ObjectChild\Properties\ID + #CRLF$ +
          ChildTab + "Object Chil X: " + *ObjectChild\Properties\X + #CRLF$ +
          ChildTab + "Object Chil Y: " + *ObjectChild\Properties\Y + #CRLF$ +
          ChildTab + "Object Chil Width: " + *ObjectChild\Properties\Width + #CRLF$ +
          ChildTab + "Object Chil Height: " + *ObjectChild\Properties\Height + #CRLF$ +
          ChildTab + "ProfondeurHierarchique: " + Str(Profondeur + 1)
    
    ; Appel récursif pour les sous-enfants
    If MapSize(*ObjectChild\Children()) > 0
      PrintHierarchieChild(*ObjectChild, Profondeur + 1, Tabulation + "  ")
    EndIf
  Next
EndProcedure

; -------------------------------
; Affichage de la hiérarchie racine
; -------------------------------
Procedure PrintHierarchie(*Object.ObjectHandle)
  If Not *Object
    ProcedureReturn 0
  EndIf
  
  ; Affichage de la racine
  Protected RootInfo.s = "      +- "
  Debug "+- Object Name: " + *Object\Properties\Name + #CRLF$ +
        RootInfo + "Object ID: " + *Object\Properties\ID + #CRLF$ +
        RootInfo + "Object X: " + *Object\Properties\X + #CRLF$ +
        RootInfo + "Object Y: " + *Object\Properties\Y + #CRLF$ +
        RootInfo + "Object Width: " + *Object\Properties\Width + #CRLF$ +
        RootInfo + "Object Height: " + *Object\Properties\Height + #CRLF$ +
        RootInfo + "ProfondeurHierarchique: 0"
  
  ; Lancement de l'affichage récursif
  PrintHierarchieChild(*Object, 0, "  ")
EndProcedure



; Création d'un Objet.
Define *MyObjectRootTomas.ObjectHandle = NewObject() ; Tomas - 1


; Définie les Propriétés
*MyObjectRootTomas\Properties\Name = "Tomas" ; Tomas - 1
*MyObjectRootTomas\Properties\X = 45         ; Tomas - 1
*MyObjectRootTomas\Properties\Y = 32         ; Tomas - 1
*MyObjectRootTomas\Properties\Width = 25     ; Tomas - 1
*MyObjectRootTomas\Properties\Height = 50    ; Tomas - 1

; Création d'un Objet.
Define *MyObjectChildMartin.ObjectHandle = NewObject() ; Martin - 2

; Définie les Propriétés
*MyObjectChildMartin\Properties\Name = "Martin" ; Martin - 2
*MyObjectChildMartin\Properties\X = 50          ; Martin - 2
*MyObjectChildMartin\Properties\Y = 35          ; Martin - 2
*MyObjectChildMartin\Properties\Width = 30      ; Martin - 2
*MyObjectChildMartin\Properties\Height = 55     ; Martin - 2

*MyObjectRootTomas\Methods\AddChild(*MyObjectChildMartin) ; Tomas - 1 > Martin - 2

; Création d'un Objet.
Define *MyObjectSubChildLucie.ObjectHandle = NewObject() ; Lucie - 3

; Définie les Propriétés
*MyObjectSubChildLucie\Properties\Name = "Lucie" ; Lucie - 3
*MyObjectSubChildLucie\Properties\X = 55         ; Lucie - 3
*MyObjectSubChildLucie\Properties\Y = 40         ; Lucie - 3
*MyObjectSubChildLucie\Properties\Width = 35     ; Lucie - 3
*MyObjectSubChildLucie\Properties\Height = 60    ; Lucie - 3

*MyObjectChildMartin\Methods\AddChild(*MyObjectSubChildLucie) ; Martin - 2 > Lucie - 3

; Création d'un Objet.
Define *MyObjectSubSubChildLuck.ObjectHandle = NewObject() ; Luck - 4

; Définie les Propriétés
*MyObjectSubSubChildLuck\Properties\Name = "Luck" ; Luck - 4
*MyObjectSubSubChildLuck\Properties\X = 60        ; Luck - 4
*MyObjectSubSubChildLuck\Properties\Y = 45        ; Luck - 4
*MyObjectSubSubChildLuck\Properties\Width = 40    ; Luck - 4
*MyObjectSubSubChildLuck\Properties\Height = 65   ; Luck - 4

*MyObjectSubChildLucie\Methods\AddChild(*MyObjectSubSubChildLuck) ; Lucie - 3 > Luck - 4

; Création d'un Objet.
Define *MyObjectSubSubChildJessica.ObjectHandle = NewObject() ; Jessica - 5

; Définie les Propriétés
*MyObjectSubSubChildJessica\Properties\Name = "Jessica" ; Jessica - 5
*MyObjectSubSubChildJessica\Properties\X = 65           ; Jessica - 5
*MyObjectSubSubChildJessica\Properties\Y = 50           ; Jessica - 5
*MyObjectSubSubChildJessica\Properties\Width = 45       ; Jessica - 5
*MyObjectSubSubChildJessica\Properties\Height = 70      ; Jessica - 5

*MyObjectSubChildLucie\Methods\AddChild(*MyObjectSubSubChildJessica) ; Lucie - 3 > Jessica - 5

; Création d'un Objet.
Define *MyObjectSubChildTome.ObjectHandle = NewObject() ; Tome - 6

; Définie les Propriétés
*MyObjectSubChildTome\Properties\Name = "Tome" ; Tome - 6
*MyObjectSubChildTome\Properties\X = 70        ; Tome - 6
*MyObjectSubChildTome\Properties\Y = 55        ; Tome - 6
*MyObjectSubChildTome\Properties\Width = 50    ; Tome - 6
*MyObjectSubChildTome\Properties\Height = 75   ; Tome - 6

*MyObjectChildMartin\Methods\AddChild(*MyObjectSubChildTome) ; Martin - 2 > Tome - 6

; Création d'un Objet.
Define *MyObjectSubSubSubChildMarine.ObjectHandle = NewObject() ; Marine - 7

; Définie les Propriétés
*MyObjectSubSubSubChildMarine\Properties\Name = "Marine" ; Marine - 7
*MyObjectSubSubSubChildMarine\Properties\X = 75          ; Marine - 7
*MyObjectSubSubSubChildMarine\Properties\Y = 60          ; Marine - 7
*MyObjectSubSubSubChildMarine\Properties\Width = 55      ; Marine - 7
*MyObjectSubSubSubChildMarine\Properties\Height = 80     ; Marine - 7

*MyObjectSubChildTome\Methods\AddChild(*MyObjectSubSubSubChildMarine) ; Tome - 6 > Marine - 7

; Création d'un Objet.
Define *MyObjectChildClaire.ObjectHandle = NewObject() ; Claire - 8

; Définie les Propriétés
*MyObjectChildClaire\Properties\Name = "Claire" ; Claire - 8
*MyObjectChildClaire\Properties\X = 80          ; Claire - 8
*MyObjectChildClaire\Properties\Y = 65          ; Claire - 8
*MyObjectChildClaire\Properties\Width = 60      ; Claire - 8
*MyObjectChildClaire\Properties\Height = 85     ; Claire - 8

*MyObjectRootTomas\Methods\AddChild(*MyObjectChildClaire) ; Tomas - 1 > Claire - 8

; Création d'un Objet.
Define *MyObjectSubChildPaul.ObjectHandle = NewObject() ; Paul - 9

; Définie les Propriétés
*MyObjectSubChildPaul\Properties\Name = "Paul" ; Paul - 9
*MyObjectSubChildPaul\Properties\X = 85        ; Paul - 9
*MyObjectSubChildPaul\Properties\Y = 70        ; Paul - 9
*MyObjectSubChildPaul\Properties\Width = 65    ; Paul - 9
*MyObjectSubChildPaul\Properties\Height = 90   ; Paul - 9

*MyObjectChildClaire\Methods\AddChild(*MyObjectSubChildPaul) ; Claire - 8 > Paul - 9

; Création d'un Objet.
Define *MyObjectSubSubChildLouis.ObjectHandle = NewObject() ; Louis - 10

; Définie les Propriétés
*MyObjectSubSubChildLouis\Properties\Name = "Louis" ; Louis - 10
*MyObjectSubSubChildLouis\Properties\X = 90         ; Louis - 10
*MyObjectSubSubChildLouis\Properties\Y = 75         ; Louis - 10
*MyObjectSubSubChildLouis\Properties\Width = 70     ; Louis - 10
*MyObjectSubSubChildLouis\Properties\Height = 95    ; Louis - 10

*MyObjectSubChildPaul\Methods\AddChild(*MyObjectSubSubChildLouis) ; Paul - 9 > Louis - 10

; Création d'un Objet.
Define *MyObjectSubSubSubChildLea.ObjectHandle = NewObject() ; Lea - 11

; Définie les Propriétés
*MyObjectSubSubSubChildLea\Properties\Name = "Lea" ; Lea - 11
*MyObjectSubSubSubChildLea\Properties\X = 95       ; Lea - 11
*MyObjectSubSubSubChildLea\Properties\Y = 80       ; Lea - 11
*MyObjectSubSubSubChildLea\Properties\Width = 75   ; Lea - 11
*MyObjectSubSubSubChildLea\Properties\Height = 100 ; Lea - 11

*MyObjectSubSubChildLouis\Methods\AddChild(*MyObjectSubSubSubChildLea) ; Louis - 10 > Lea - 11

; Création d'un Objet.
Define *MyObjectSubSubSubChildJules.ObjectHandle = NewObject() ; Jules - 12

; Définie les Propriétés
*MyObjectSubSubSubChildJules\Properties\Name = "Jules" ; Jules - 12
*MyObjectSubSubSubChildJules\Properties\X = 100        ; Jules - 12
*MyObjectSubSubSubChildJules\Properties\Y = 85         ; Jules - 12
*MyObjectSubSubSubChildJules\Properties\Width = 80     ; Jules - 12
*MyObjectSubSubSubChildJules\Properties\Height = 105   ; Jules - 12

*MyObjectSubSubChildLouis\Methods\AddChild(*MyObjectSubSubSubChildJules) ; Louis - 10 > Jules - 12

; Création d'un Objet.
Define *MyObjectSubSubChildEmma.ObjectHandle = NewObject() ; Emma - 13

; Définie les Propriétés
*MyObjectSubSubChildEmma\Properties\Name = "Emma" ; Emma - 13
*MyObjectSubSubChildEmma\Properties\X = 105       ; Emma - 13
*MyObjectSubSubChildEmma\Properties\Y = 90        ; Emma - 13
*MyObjectSubSubChildEmma\Properties\Width = 85    ; Emma - 13
*MyObjectSubSubChildEmma\Properties\Height = 110  ; Emma - 13

*MyObjectSubChildPaul\Methods\AddChild(*MyObjectSubSubChildEmma) ; Paul - 9 > Emma - 13

; Création d'un Objet.
Define *MyObjectSubChildSophie.ObjectHandle = NewObject() ; Sophie - 14

; Définie les Propriétés
*MyObjectSubChildSophie\Properties\Name = "Sophie" ; Sophie - 14
*MyObjectSubChildSophie\Properties\X = 110         ; Sophie - 14
*MyObjectSubChildSophie\Properties\Y = 95          ; Sophie - 14
*MyObjectSubChildSophie\Properties\Width = 90      ; Sophie - 14
*MyObjectSubChildSophie\Properties\Height = 115    ; Sophie - 14

*MyObjectChildClaire\Methods\AddChild(*MyObjectSubChildSophie) ; Claire - 8 > Sophie - 14

; ; Pour visualiser l'arbre généalogique
; Procedure DisplayFamilyTree(*Object.ObjectHandle, Level = 0)
;   Debug (Space(Level * 6) + "+- " + *Object\Properties\Name)
;   ForEach *Object\Children()
;     DisplayFamilyTree(*Object\Children(), Level + 1)
;   Next
; EndProcedure

; DisplayFamilyTree(*MyObjectRootTomas.ObjectHandle, 0)

; +- Tomas
;       +- Claire
;             +- Paul
;                   +- Louis
;                         +- Lea
;                         +- Jules
;                   +- Emma
;             +- Sophie
;       +- Martin
;             +- Lucie
;                   +- Luck
;                   +- Jessica
;             +- Tome
;                   +- Marine
; 

; Affichage de l'arbre complet
PrintHierarchie(*MyObjectRootTomas)

; Nettoyage final
If DeleteObject(*MyObjectRootTomas)
  *MyObjectRootTomas = #Null ; Bonne pratique anti-dangling pointer
  Debug "Nettoyage réussi !"
Else
  Debug "Échec du nettoyage !"
EndIf
J'aurais souhaiter rendre la table virtuel privé au module et non accessible en dehors du module, je n'y arrive pas.
Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.
Avatar de l’utilisateur
Micoute
Messages : 2583
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: La POO pour les nuls

Message par Micoute »

Je comprends ce que tu veux faire Shadow, mais ce n'est que de la pseudo POO, car PB est un environnement de programmation procédurale.
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 6.20 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Répondre