[Basic] Programmation orientée objet

Venez découvrir tous les tutoriels, modèles et autres foires aux questions afin de maîtriser rapidement votre suite bureautique favorite.

Modérateur: Vilains modOOs

Règles du forum
Aucune question dans cette section !
Cette section est faite pour présenter les tutoriels. Si vous avez une question sur l'installation, le fonctionnement ou l'utilisation, vous devez poster dans la section du module où se produit le problème.

[Basic] Programmation orientée objet

Messagepar JPL » 07 Déc 2012 13:15

Un secret bien gardé.

La définition en BASIC de modules de classes est parfaitement possible comme cela l'est en Visual Basic.
Le niveau de sophistication de ces modules et leur syntaxe est comparable à ce qu'ils sont en VB6.
La suite de ce sujet en illustre les possibilités par quelques exemples.

Comment procéder ?

Définition d'une classe :
Code : Tout sélectionner   AgrandirRéduire
Option Compatible
Option ClassModule

Option Explicit

REM -----------------------------------------------------------------------------------------------------------------------
REM --- Internal Variables                                                                           ---
REM -----------------------------------------------------------------------------------------------------------------------

Private _X      As Double
Private _Y      As Double

REM -----------------------------------------------------------------------------------------------------------------------
REM --- CONSTRUCTORS / DESTRUCTORS                                                                    ---
REM -----------------------------------------------------------------------------------------------------------------------
Private Sub Class_Initialize()
'   Default point = Origin of axis
   _X = 0
   _Y = 0
End Sub      '   Constructor

REM -----------------------------------------------------------------------------------------------------------------------
Private Sub Class_Terminate()
   _X = - 4.94065645841247E-324      '   Most negative value allowed for Double variables
   _Y = - 4.94065645841247E-324
end sub

REM -----------------------------------------------------------------------------------------------------------------------
REM --- CLASS GET/LET/SET PROPERTIES                                                                 ---
REM -----------------------------------------------------------------------------------------------------------------------

Public Property Get X As Double
   X = _X
End Property

Public Property Let X(ByVal pValue As Double)
   _X = pValue
End property

REM -----------------------------------------------------------------------------------------------------------------------
Public Property Get Y As Double
   Y = _Y
End Property

Public Property Let Y(ByVal pValue As Double)
   _Y = pValue
End property

REM -----------------------------------------------------------------------------------------------------------------------
Public Property Get Dummy As Variant
   Dummy = Null
End Property

REM -----------------------------------------------------------------------------------------------------------------------
REM --- CLASS METHODS                                                                              ---
REM -----------------------------------------------------------------------------------------------------------------------

Public Sub Move(ByVal pX As Double, ByVal pY As Double)
   _X = _X + pX
   _Y = _Y + pY
End Sub

Si ce code est saisi dans un module nommé « Point » le nom de la classe sera également « Point ».

Les lignes « Option Compatible » et « Option ClassModule » en tête du module sont celles qui déterminent la caractéristique du module, à savoir qu'il s'agit d'un module de classe. Elles doivent se trouver dans l'ordre indiqué. Dans le cas contraire, la source ne passera pas la compilation.

Un module de classe contient un certain nombre de Variables Internes. Elles sont regroupées en-dehors des function/sub et reçoivent généralement l'attribut « Private ». Il signifie que la variable interne ne peut être utilisée que dans le module même, contrairement à la valeur « Public ». A noter que cet attribut est ignoré en Basic. Les variables concernées peuvent être de tout type, y compris une autre classe. Un exemple sera donné plus bas. Une variable interne peut également contenir un objet UNO.

Les Sub « Class_Initialize » et « Class_Terminate » sont resp. Les constructeur et destructeur de la classe. Elles sont exécutées, pour la première, avant la première utilisation d'une instance de classe, pour la seconde, lors de sa suppression (voir plus bas).

Les propriétés sont déterminées par les définitions « Property Get », « Property Let » et « Property Set ». « Get » fournit la valeur de la propriété, « Let » correspond à une assignation classique, « Set » permet la transmission d'objets ou de structures complexes. Notez que la valeur retournée par « Property Get » ainsi que l'argument de « Property Let » doivent être de TYPE IDENTIQUE.
A noter que l'instruction « Exit » s'enrichit d'une option « Exit Property ».

Les méthodes sont des Sub ou des Function. Une Sub exécute une action quelconque et représente le cas le plus fréquent d'une méthode.

Utilisation de la classe « Point »:

La déclaration d'une instance de classe se fait par l'instruction « Dim ». La variable associée sera déclarée comme « Object ».
L'instruction « Set » crée l'instance et exécute le constructeur.

Code : Tout sélectionner   AgrandirRéduire
   Dim a As Object
   Set a = New Point
   a.X = 4
   a.Y = 1
   MsgBox a._X

Le code ci_dessous est fonctionnellement équivalent au précédent et en constitue une variante plus concise.
Toutefois il faut comprendre que le constructeur ne sera exécuté qu'à la première utilisation de la variable « a », soit à l'instruction « a.X = 4 ». Ceci signifie que pour chaque instruction entre la déclaration de la variable et sa première utilisation l'interpréteur insérera du code pour savoir s'il y a lieu de déclencher le constructeur.
Personnellement je privilégierai en conséquence la forme précédente.

Code : Tout sélectionner   AgrandirRéduire
   Dim a As New Point
   a.X = 4
   a.Y = 1
   MsgBox a._X


Définition de la classe « Circle »

Code : Tout sélectionner   AgrandirRéduire
Option Compatible
Option ClassModule

Option Explicit

REM -----------------------------------------------------------------------------------------------------------------------
REM --- Internal Variables                                                                        ---
REM -----------------------------------------------------------------------------------------------------------------------

Private _R      As Double
Private _Center   As Object

REM -----------------------------------------------------------------------------------------------------------------------
REM --- CONSTRUCTORS / DESTRUCTORS                                                                    ---
REM -----------------------------------------------------------------------------------------------------------------------
Private Sub Class_Initialize()
'   Default circle = Null circle at axis origin
   _R = 0
   Set _Center = New Point
End Sub      '   Constructor

REM -----------------------------------------------------------------------------------------------------------------------
Private Sub Class_Terminate()
   _R = 0
   Erase _Center
End Sub

REM -----------------------------------------------------------------------------------------------------------------------
REM --- CLASS GET/LET/SET PROPERTIES                                                                 ---
REM -----------------------------------------------------------------------------------------------------------------------

Property Get R As Double
   R = _R
End Property

Public Property Let R(ByVal pValue As Double)
   _R = pValue
End property

REM -----------------------------------------------------------------------------------------------------------------------
Public Property Get Center As Object
   Set Center = _Center
End Property

Property Set Center(ByVal pValue As Object)
   Set _Center = pValue
End property

REM -----------------------------------------------------------------------------------------------------------------------
Public Function Area() As Double
   Area = PI() * R * R
End Function

Public Function Circumference() As Double
   Circumference = 2 * PI() * R
End Function

REM -----------------------------------------------------------------------------------------------------------------------
Public Property Get Dummy As Variant
   Dummy = Null
End Property

REM -----------------------------------------------------------------------------------------------------------------------
REM --- CLASS METHODS                                                                              ---
REM -----------------------------------------------------------------------------------------------------------------------

Public Sub MoveHoriz(ByVal pValue)      '   pValue might be negative
   _Center.Move(pValue, 0)
End Sub

Public Sub MoveVert(ByVal pValue)         '   pValue might be negative
   _Center.Move(0, pValue)
End Sub

REM -----------------------------------------------------------------------------------------------------------------------
Public Function IntersectX() As Variant
'   Return intersection points of circle with X-axis
'   Substitute y = 0 in circle equation (x-Cx)2 + (y-Cy)2 = R2
'      => Equation of degree 2 with unknown x
Dim a As Double, b As Double, c As Double, dDiscr As Double
   a = 1
   b = -2 * _Center.X
   c = (_Center.X ^ 2) + (_Center.Y ^ 2) - (R ^ 2)
   dDiscr = (b ^ 2) - (4 * a * c)

Dim oInterSect1 As Object, oInterSect2 As Object
   Select Case True
      Case dDiscr < 0      :   InterSectX = Array()
      Case dDiscr = 0
         Set oInterSect1 = New Point
         oInterSect.X = -b / (2 * a)
         Set InterSectX = Array(oInterSect)
      Case Else
         Set oInterSect1 = New Point
         Set oInterSect2 = New Point
         oInterSect1.X = (-b - Sqr(dDiscr)) / (2 * a)
         oInterSect2.X = (-b + Sqr(dDiscr)) / (2 * a)
         InterSectX = Array(oInterSect1, oInterSect2)
   End Select
End Function


Spécificités :

Une des variables internes est une instance de la classe « Point ».

Une function, telle « Area », outre les actions qu'elle peut exécuter, retourne de surcroît une valeur. Quelle est la différence entre « Property Get Area() » et « Public Function Area() » ? Il n'y en a pas sauf en ce qui concerne leur traitement par le debugger. Voir plus bas.

Le destructeur « Class_Terminate » contient une instruction « Erase » qui, elle-même, active le destructeur de l'objet « _Center » de type « Point ».

Les méthodes « MoveHoriz » et « MoveVert » font appel à la méthode « Move » de la classe « Point » appliquée à la variable interne « _Center ».

Exemples :

- Avec illustration de l'instruction « With » ainsi que des propriétés en cascade « b.Center.X » :

Code : Tout sélectionner   AgrandirRéduire
   Dim a As Object
   Set a = New Point
   a.X = 2
   a.Y = 1
   Dim b As Object
   Set b = New Circle
   With b
      .R = 2
      Set .Center = a
      .MoveHoriz(2)   '   Center becomes (4,1)
      MsgBox "Circle centered on (" & .Center.X & "," & .Center.Y & "). Circumference = " & .Circumference
   End With
   Erase b


- L'exemple suivant illustre la méthode IntersectX qui retourne un tableau de « Points » d'intersection entre une instance de type « Circle » et l 'axe des X : il peut y avoir 0, 1 ou 2 points d'intersection.

Code : Tout sélectionner   AgrandirRéduire
   Dim b As Object
   Set b = New Circle
   b.Center.X = 4
   b.Center.Y = 1
   b.R = 2
   Dim vPoints As Variant, i As Integer
   vPoints = b.IntersectX()   '   Return an array of Points objects
   For i = LBound(vPoints) To UBound(vPoints)
      MsgBox vPoints(i).X
   Next i


Debugging :

L'utilisation de Xray est inutile. En effet aucune information utile sur une instance de classe ne proviendra de cet outil. Cependant son exécution sur un tel objet se passe sans douleur.

Le comportement du debugger de l'IDE est différent. Soit l'exécution se trouve à l'intérieur de la classe, dans ce cas les variables internes de l'instance (en plus des variables locales de la routine en cours ...) sont visualisables en mentionnant simplement leur nom. Soit l'exécution est en-dehors de la classe, dans ce cas la visualisation d'une variable passera par le calcul par le debugger de chaque propriété de la classe ! Super, car même si une des propriétés est elle-même une instance de classe, l'arborescence est bien gérée.
Toutefois ceci signifie :
- que si le calcul de la propriété contient une erreur, le debugger commettra la même erreur, d'où l'intérêt parfois d'utiliser temporairement pendant la mise au point « Function » plutôt que « Property Get »;
- que si vous êtes en mode pas-à-pas, le pas-à-pas s'engage à son tour et sous l'impulsion du debugger sur la voie des différentes « Property Get » ..., ce qui entraîne à coup sûr et rapidement un crash de AOO/LibO.

La propriété « Dummy » a été insérée dans chacun des modules de classe simplement parce que le debugger affiche dans l'IDE toutes les propriétés, sauf, bizarrement, la dernière ... ?

En conclusion : visualiser une variable de classe, oui, mais si le calcul des propriétés est au point, et, une fois visualisée, retirer la variable des variables observées avant de poursuivre l'exécution.

Autres remarques :

Basic supporte également le verbe « Implements » comme en VB6. Son usage me paraît cependant peu utile.
VB6 accepte également l'usage dans un module de classe du mot-clé « This » pour désigner l'instance courante en exécution. De plus il permet le passage de l'objet traité comme argument d'une fonction externe au module. Ceci n'est pas possible en Basic, à ma connaissance.
L'héritage entre classes d'objets n'est pas possible. Le verbe « Inherits » n'est implémenté d'ailleurs en VB que dans les versions postérieures à VB6.

J'espère que ces explications vous seront profitables ...
JPL
Dernière édition par JPL le 10 Déc 2012 10:07, édité 1 fois.
Windows 7 / OOo 4.0 / LibO 4.1
Ubuntu 13.10 / LibO 4.1
JPL
NOOuvel adepte
NOOuvel adepte
 
Message(s) : 20
Inscrit le : 17 Mars 2012 11:16

Re: [Basic] Programmation orientée objet

Messagepar Churay » 10 Déc 2012 14:21

Bonjour

A toutes fins utiles :




Le modérateur a écrit:Aucune question dans ce fil, veuillez poster en section Macro & API
Avatar de l’utilisateur
Churay
ManitOOu
ManitOOu
 
Message(s) : 2665
Inscrit le : 30 Avr 2009 05:54
Localisation : CATALUNYA


Retour vers Tutoriels

Qui est en ligne ?

Utilisateur(s) parcourant ce forum : Aucun utilisateur inscrit et 6 invité(s)