Compréhension : POO & Interfaces

Partagez votre expérience de PureBasic avec les autres utilisateurs.
LeCyb
Messages : 273
Inscription : dim. 26/déc./2004 20:49

Compréhension : POO & Interfaces

Message par LeCyb »

Voici une méthode "simple" pour faire des de la Programmation Orientée Objet dans PB.
Le but n'étant pas d'expliquer les classes, héritages et autres surcharges mais bien de montrer un code qui fonctionne et "simple".

Pour approfondir la chose j'ai trouvé un tuto très complet et en Français sur le sujet fait par Dräc:
http://drac.site.chez.tiscali.fr/Tutori ... ls.htm#POO

Le principe de cet exemple est de faire un "composant" qui va réaliser une addition (c'est con mais c'est simple).
Les interfaces étant ce qu'elles sont il faut savoir qu'il n'y a que des procédures qui seront "visibles" pendant l'utilisation de l'objet.
Afin d'avoir des "propriétés" liées à l'objet on détournera les variables "internes" de l'objet en créant des procédures (SetX, GetX...).
Ce subterfuge va permettre d'avoir plusieurs objets avec des propriétés différentes au lieu d'une simple liste de fonctions.

Code : Tout sélectionner

; Déclaration des fonctions de notre objet dans une Interface.
; Lors de l'utilisation de l'objet le programmeur ne verra que ça
; et donc il faudra implémenter des fonctions pour modifier
; et récupérer les "propriétés" de notre objet.
Interface Math_Object
  SetX(x)
  GetX.l() ;<-- cette procédure retourne une valeur donc on indique le type
  SetY(y)
  Add.l()
  Free()
EndInterface

; Déclaration d'une structure pour y stocker les adresses des procédures.
; Il faudra une déclaration par procédure utilisée dans l'objet
; et elles seront toutes de type Long (pour stocker l'adresse).
; Pour des raisons obscures il faut impérativement garder EXACTEMENT
; le même ordre que pour l'interface.
Structure Math_Functions_Addresses
  SetX.l
  GetX.l
  SetY.l
  Add.l
  Free.l
EndStructure

; Déclaration de la structure "interne" de l'objet, càd la structure
; des procédures ainsi que les variables (les propriétés de l'objet).
Structure Math_Internal_Structure
  *Virtual.Functions_Addresses
  x.l ;<-- variable interne, peut être de n'importe quel type
  y.l
EndStructure

; Nos procédures

; Le paramètre *Object permet de faire référence à l'objet en lui même
; et est obligatoire dans le cas où on veut accéder à ses "propriétés".
Procedure SetX(*Object.Math_Internal_Structure, x)
  *Object\x = x ;<-- ici on change la valeur de la propriété x.
EndProcedure

Procedure.l GetX(*Object.Math_Internal_Structure)
  ProcedureReturn *Object\x
EndProcedure

Procedure SetY(*Object.Math_Internal_Structure, y)
  *Object\y = y
EndProcedure

Procedure.l Add(*Object.Math_Internal_Structure) 
  ProcedureReturn *Object\x + *Object\y 
EndProcedure 

; Ceci est le "destructeur", càd qu'il va permettre de libérer la mémoire
; et donc de détruire l'objet.
; C'est un simple FreeMemory mais il peut être utile d'effectuer diverses
; tâches comme fermer un fichier ou une connexion réseau.
Procedure Free(*Object.Math_Internal_Structure)
  FreeMemory(*Object)
EndProcedure

; Ici on va déclarer une variable globale qui va contenir les adresses
; de nos procédures.
; Il est important de ne pas modifier ces valeurs à l'exécution.
Global  Math_Global.Math_Functions_Addresses
Math_Global\SetX = @SetX()
Math_Global\GetX = @GetX()
Math_Global\SetY = @SetY()
Math_Global\Add = @Add()
Math_Global\Free = @Free()

; Déclaration du "constructeur". Contrairement au destructeur il va
; allouer l'espace mémoire pour l'objet.
; Si cette procédure est appellée 10 fois il faudra détruire les
; 10 objets créés. La valeur retournée est le pointeur de cet objet.
; Remarque: c'est la seule procédure qui ne doit pas se trouver dans
; l'interface vu que l'objet n'existe pas encore.
Procedure.l NewMath_Object()
  *new.Math_Internal_Structure = AllocateMemory(SizeOf(Math_Internal_Structure))
  *new\Virtual = Math_Global
  ProcedureReturn *new
EndProcedure

;-------------------
;Testons la chose :)
;-------------------

MonMath.Math_Object = NewMath_Object() ;<-- création de l'objet

; Utilisation des procédures de l'objet 
MonMath\SetX(5) 
MonMath\SetY(2) 
Debug MonMath\Add() 
Debug MonMath\GetX()

; On oublie pas de détruire l'objet 
MonMath\Free() 
Je rappelle que le but n'est pas d'expliquer de long en large l'utilisation des structures mais de montrer que la création d'un objet est à la portée de tous.

Pour créer une librairie avec un objet dedans il faudra faire quelques modifications:
- Changer Procedure par ProcedureDLL
- Mettre dans une procédure "_Init" (voir doc Tailbite) l'assignation des adresses (ce qui suit le Global).
- Laisser le Global, l'interface et les structures comme elles sont.
Dernière modification par LeCyb le ven. 30/sept./2005 23:56, modifié 1 fois.
Vive le thread-safe !
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message par Droopy »

Syntax error

Code : Tout sélectionner

Debug MonMath\GetX() 
T'as une idée ?
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

erreur dans l'interface

Code : Tout sélectionner

Interface Math_Object
  SetX(x)
  GetX.l() ;<-- cette procédure retourne une valeur donc on indique le type
  SetY(y)
  ADD.l()
  Free()
EndInterface
Dri ;)
LeCyb
Messages : 273
Inscription : dim. 26/déc./2004 20:49

Message par LeCyb »

Faute de frappe, c'est corrigé :D

Sinon vous en pensez quoi (surtout ceux qui maîtrisent la chose) ?
Vive le thread-safe !
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message par Droopy »

Suite à l'excellent article de Drac, ça faisait longtemps que je voulais pouvoir comparer la programmation procédurale à la Poo.

Personnelement, pour additionner deux valeurs, je préfère utiliser la méthode procédurale, qui je trouve est bien moins compliquée .
fweil
Messages : 505
Inscription : dim. 16/mai/2004 17:50
Localisation : Bayonne (64)
Contact :

Message par fweil »

LeCyb,

Quand je lis c'est con mais c'est simple, je suis totalement preneur ... respect !

En fait quand c'st simple, c'est beaucoup moins con qu'il n'y paraît.

La petite synthèse que tu présente ici est tout à fait utile pour comprendre.

C'est vrai qu'au départ faire de la POO pour modéliser c = a + b, ça paraît simpliste, mais on rentre bien dans la méthode. Et comme le résultat fonctionne, ça permet d'aller plus loin.
Mon avatar reproduit l'image de 4x1.8m présentée au 'Salon international du meuble de Paris' en janvier 2004, dans l'exposition 'Shades' réunisant 22 créateurs autour de Matt Sindall. L'original est un stratifié en 150 dpi.
LeCyb
Messages : 273
Inscription : dim. 26/déc./2004 20:49

Message par LeCyb »

@Droopy, comme le souligne fweil j'ai essayé de faire simple et une addition faisait l'affaire pour exprimer l'exemple.

Maintenant pour te rendre mieux compte de la puissance de la chose je vais juste te présenter un autre exemple.

Imagine une librairie "FTP" avec un système d'interfaces. On aurait des propriétés telles que le serveur, le port, le login/pass etc...
Et on aurait des méthodes du genre connect, getfile etc...

Code : Tout sélectionner

MonFtp = NewFTP_Object()
MonFtp\Server = "127.0.0.1"
MonFtp\Port = 21
MonFtp\User = "user"
MonFtp\Password = "password"
If MonFtp\Connect() = 0
  If MonFtp\Login() = 0
    ...
  Else
    MessageRequester("Error", MonFtp\LastErrorMessage)
  EndIf
Else
  MessageRequester("Error", MonFtp\LastErrorMessage)
EndIf
MonFtp\Free()
Tu pourrais tout aussi bien imaginer gérer des monstres et des personnages dans un jeu en faisant un Monstre_Object et Player-Object qui pourraient avoir diverses propriétés et fonctions comme la vita, le déplacement et bien d'autres trucs.
Vive le thread-safe !
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message par Droopy »

Effectivement ça peut simplifier la maintenance .
Oliv
Messages : 2117
Inscription : mer. 21/janv./2004 18:39

Message par Oliv »

C'est vrai que vu comme ça ça peut être pratique, merci :D mais ça doit quand même pas mal changer de nos habitudes de faire comme ça non ?
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

@LeCyb
Je viens de comprendre pourquoi tu tiens tant aux interfaces (presqu'autant qu'au thread safe :P)

Dri :lol:
Répondre