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 .
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)
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()