OVH Cloud OVH Cloud

Variable commune entre les classes d'un projet ?

11 réponses
Avatar
L'AMI Yves
Voila : je veux créer un objet qui contient une collection de sous objets.
Je crée donc un projet qui contient plusieurs classes : une pour l'objet
de base, une pour la collection, une pour les sous-objets de la collection.
Jusque là, ça marche.

Je veux doter mon objet d'une nouvelle propriété : "Modifié", qui
deviendra "Vraie" si l'un des objets de la collection est modifié. Cette
propriété sera (évidemment) en lecture seule pour l'instance d'objet.

J'essaie donc de déclarer une variable "Friend" au niveau de la
classe de l'objet de base, et je la gère dans la classe
des sous_objet (ou de la collection, d'ailleurs, dans les méthodes
Add et Remove).

Or, dans les classes qui ne sont pas celle où elle est déclarée "Friend",
VB me dit que cette variable n'est pas déclarée.

Est-ce un bug du compilateur, ou est-ce moi qui n'ai pas compris
l'instruction Friend (ou le concept d'assembly) ?

Merci si vous voulez bien m'aider...

1 réponse

1 2
Avatar
Patrice
Non ce n'est pas cela.

Une "assembly" est une unité de déploiement (en gros une DLL générée par un
projet). Le mot clé Friend permet effectivement de réduire la portée de la
variable au code qui se trouve dans le même projet.

Le problème est que tu cherches à modifier dans un objet de type "Sections",
l'objet Ini qui "possède" cet objet. Il faut donc bien que tu accèdes à
l'objet parent qui possède l'objet Sections que tu es en train de modifier.
Ton code essaie de modifier le parent (d'après ce que je comprends) mais en
utilisant une variable "Ini" qui n'est pas déclarée.

J'ai l'impression que tu t'attends peut-être à ce que cela soit automatique
mais n'oublie pas que le même objet peut très bien être affecter à plusieurs
instances d'un objet de type ini ou être également utilisée individuellement
. Ce n'est pas parce qu'une classe A possède comme membre un object de
classe B que le compilateur est capable de retrouver pour un objet de type B
quel est l'objet A qui lui fait référence (car il peut y en avoir aucun ou
plusieurs et il peut y avoir plein d'autres objets d'autres types qui
référencent également cet objet de type B sans que le savoir ait un intérêt
particulier). Il faut donc garder explicitement cet relations si tu en as
besoin.

Si tu reprends par exemple le modèle Excel tu verras que les objects on
souvent une propriété qui permet d'accéder à leur parent.

Une autre approche serait de garder cet indicateur au niveau de l'objet
sections, Ini se contentant de relayer l'info. Voir aussi si cet objet ini
est utile (peut-être les deux classes pourraient-elle n'en faire qu'une
etc..). La première solution evoquée donnerait par exemple (par contre si tu
passes quelque part un object Sections tu ne pourras plus accéder à son
parent) :

Class Ini
Friend ReadOnly Property Updated() As Boolean
Get
Return Sections.Updated
End Get
End Property
Friend Sections As New Sections
End Class

Class Sections
Friend Updated As Boolean
Sub Touch()
Updated = True
End Sub
End Class

Public Class App
Shared Sub Main()
Dim ini As New Ini
MsgBox(ini.Updated)
ini.sections.Touch()
MsgBox(ini.Updated)
End Sub
End Class


Essaie peut-être de trouver une intro sur la POO comme
http://xo.developpez.com/tutoriel/vb.net/poo/ avant de te lancer...

--
Patrice

"L'AMI Yves" a écrit dans le message de
news: 455cdaa5$0$7754$
Je pense que tu as compris le principe, mais ça me paraît diablement
compliqué. Alors que le seul problème à résoudre, c'est la portée de
la variable Modif.... D'après la doc, j'avais compris que si toutes mes
déclarations de classe étaient dans le même fichier, cet ensemble
constituait ce qu'ils appellent un "Assembly", et que la déclaration
"Friend" donnait à la variable la portée de l'Assembly. C'est pas ça ?

AMIcalement.

"Patrice" a écrit dans le message de news:

Dans ton cas, je pense comprendre finalement qu'il te manque dans la
classe Sections, le moyen d'accéder à l'objet parent de type Ini qui la
possède.

Cela pourrait donner par exemple quelque chose comme (attention
simplification, il faudrait par exemple que l'on puisse pas affecter un
object sections d'un objet ini à l'autre car ce n'est plus alors le bon
parent qui serait modifié).

Class Ini
Friend Updated As Boolean
Friend Sections As New Sections(Me) ' Créer l'objet en lui passant son
parent
End Class

Class Sections
Private _Parent As Ini
Friend Sub New(ByVal Parent As Ini)
' Mémoriser le parent
_Parent = Parent
End Sub
Sub Touch()
' Mettre à jour l'indicateur du parent
_Parent.Updated = True
End Sub
End Class

Public Class App
Shared Sub Main()
Dim ini As New Ini
MsgBox(ini.Updated)
ini.sections.Touch()
MsgBox(ini.Updated)
End Sub
End Class

--

"L'AMI Yves" a écrit dans le message de
news: 455c96cf$0$2282$
J'ai dit que je programmais depuis 20 ans, et c'est vrai, et même plus,
mais c'est la première fois que je m'essaie à programmer des objets (non
pas à programmer _avec_ des objets), et je ne maîtrise sans doute pas
encore tous les concepts. Mon objet "Ini" contient un sous-objet
"Sections", tout comme en excell un objet "Row" contient un sous-objet
"Cells". Cette situation se produit dans "la vie réelle", c'est à dire
quand
on utilise une instance de la classe Ini dans un programme. Pour la
classe Ini, il y a un module de classe qui contient des déclarations
"Public", comme les Properties, accessibles depuis les autres classes ou
depuis "la vie réelle", et aussi des déclarations "Private", qui
protègent
les objets concernés de toute modification venue de l'extérieur. Ce que
j'ai compris de la déclaration "Friend", c'est que l'objet concerné (ici
une variable booléenne) était accessible de tout "l'assembly", c'est à
dire que les programmes de "Property" de la classe "Sections"
pouvaient le modifier. A mon sens, ce n'est pas un problème
d'instanciation, dans la mesure où deux objets Ini1 et Ini2 pourraient
être modifiés indépendamment l'un de l'autre, donc ils possèdent bien
chacun sa propriété "Modified". D'après ce que j'ai compris de "Shared",
ce serait utile par exemple pour attribuer un numéro d'employé
incrémenté à chaque création d'un nouvel objet Employé : rien à voir
ici : je veux que la visibilité de ma variable s'étende à toutes les
classes
de mon projet, et pas au dehors. Il me semblait que c'était là le
concept
d'Assembly, et que Friend faisait justement ça, mais je n'ai rien trouvé
qui m'aide dans la doc sur Assembly ou Assemblys : comment déclarer
explicitement quelles classes en font partie, et tout ça. Comment aussi
déclarer qu'une classe ("Sections") n'a d'existence que comme propriété
d'un "Parent ("Ini").

Je ne sais pas si je vous ai compris, ni si vous m'avez compris, mais je
ne
me trouve pas éclairé par vos deux réponses.

Merci quand même, et, si possible, essayez encore....

AMIcalement.

"Patrice" a écrit dans le message de news:

Public Class Ini déclare une classe mais ne crée pas un objet. L'objet
Ini que tu utilises plus loin n'existe donc pas et l'erreur parait tout
à fait normale.

- Soit il faut voir quel est ce fameux objet Ini que tu utilises mais
qui n'est pas déclaré.

- Soit tu veux que ce soit un membre de classe et tu as oublié le mot
clé "Shared".

Je peux difficilement en dire plus car je ne vois pas le rapport exact
entre la classe Ini et la classe Sections...

--
Patrice

"L'AMI Yves" a écrit dans le message de
news: 455c71f3$0$20555$
Tu sais, il y a vingt ans que je fais du développement, alors des
erreurs, j'en
ai vu, et même dans les compilateurs...

Mais voici des extraits de mon code, tu comprendras peut-être mieux :

Public Class Ini ' Création de l'objet Ini
Private nameValue As String
...
Friend Modif As Boolean
...
Public Property Name() As String
Get
Name = nameValue
End Get
Set(ByVal value As String)
nameValue = value
Modif = True
End Set
End Property

...
Public ReadOnly Property Modified() As Boolean
Get
Modified = Modif
End Get
End Property
...
End Class

Public Class Sections ' Création de la collection de sous-objets
Sections
Implements System.Collections.IEnumerable
Private colSections As New Collection

Public Function Add(ByVal Name As String) As Section
Dim nouveau As New Section
nouveau.Name = Name
colSections.Add(nouveau, name)
Add = nouveau
Ini.Modif = True
^^^^^^^
...

Si je mets "Ini.", il me dit qu'il faut une référence d'objet
pour une référence à un membre non partagé.
Si je ne le mets pas, il me dit que le nom n'est pas déclaré.
Peut-être faut-il quelque chose de plus dans les déclarations des
classes,
ou même avant la première, mais justement, c'est ça ma question.

Merci.


Si le compilateur te dit que ta variable n'est pas déclarée, c'est
qu'il y a un problème de visibilité.

Comment tu essaye d'avoir accès à ta variable ? Tu dois faire
référence à la classe où elle a été déclarée :
ClassDéclarante.Variable = Valeur

Est ce que la classe dans laquelle tu déclare ta variable n'est pas
plus restrictive que friend ?


Est-ce un bug du compilateur, ou est-ce moi qui n'ai pas compris
l'instruction Friend (ou le concept d'assembly) ?



C'est marrant, très souvent, les gens qui rencontrent un problème
avec de programmation, pense tout de suite qu'il s'agit d'un bug du
compilateur ou du langage. Alors que 99 fois sur 100 cela vient
d'eux.


Merci si vous voulez bien m'aider...




Dis moi si ça marche.
A plus.



















1 2