24. oktober 2002 - 09:03Der er
15 kommentarer og 1 løsning
Klasse-hieraki - global statisk pointer til roden ?
Jeg forsøger at bygge en objektmodel til et program, dvs. et klasse-hieraki. Roden i dette hieraki er klassen "Application". Jeg anvender VB6 til dette.
Det er nødvendigt at klasserne selv kan referere til andre klasser i hierakiet, ikke nødvendigvis med sig selv som udgangspunkt. Det vil kunne løses med en statisk pointer til rodklassen, men det kan jeg ikke få til at virke.
Jeg har forsøgt at tilføje et modul til projektet med følgende erklæring: Public g_Application As Application og så initiere denne variabel i Class Application's Class_Initialize()-rutine.
Men VB6 afviser denn konstruktion med en "Run-time error '91' - Object variable ... not set" når jeg tilgår denne variabel.
Hvordan får jeg lavet en global statisk pointer til min rod-klasse, som alle klasser kan tilgå ?
Ja, det er meningen at klasserne blot skal registreres, og at rodklassen oprettes vha. brugerens program med CreateObject, hvorefter den opretter resten af hierakiet.
Application-objektet, som er roden af hierakiet, skal jo skabes i et eksternt program (f.eks. vha. CreateObject i VB). Det er et klassebibliotek jeg laver.
Oprettelsen af hierakiet efter denne bruger-initiering går fint, men jeg kan ikke finde ud af at gemme referencen til dette (ene) Application-objekt, så alle klasser kan anvende denne variabel til at referere til alle andre klasser (via diverse properties og metoder på Application).
Jeg kan godt være mere specifik i hvad det skal bruges til, men så tror jeg detaljerne vil overskygge essensen af problemet.
Du skal have tak for forsøget ocp. Jeg er naturligvis også interesseret i, hvis en person autoritativt kan sige at det jeg forsøger er umuligt, og som kan anvise en brugbar alternativ metode til at opnå samme resultat.
Hvis jeg forstår dig rigtigt, så vil du have en instance af din class som svarer til den instance som client programmet har oprettet. Som f.eks. i subclassing. Du kan finde en pointer til dig selv via ObjPtr(Me) i class'en. derefter skal du bruge api'et RtlMoveMemory (CopyMemory i API-Viewer) til at 'flytte' referencen til din lokale variabel af Class'en selv. ObjPtr(Me) har altid en længde på 4 bytes, hvilket svarer til længden af pointeren. Så i pseudo kode:
1) opret variabel af Application 2) find ObjPtr(Me) 3) flyt memory pointeren fra 2) til 1)
Håber det er det svar du leder efter? Hvis ikke tror jeg ikke jeg er helt sikker på at jeg forstår spørgsmålet.
Jeg er ikke helt sikker på at det er det jeg leder efter. Jeg har som sagt opbygget et klassebibliotek (hieraki), med rodobjektet som top/indgang.
1. Brugerens program opretter "blot" mit rodobjekt vha. CreateObject("myClassLib.Application") 2. I rodobjektets Class_Initialize() opbygger jeg resten af objektmodellen, som hægtes lodret sammen, dvs. parent-child og med collections passende steder. 3. De enkelte klasseinstanser skal kunne finde andre klasseinstanser (overalt i modellen), og det er her pointeren til rodobjektet kommer ind. Med en sådan pointer kan klasserne søge sig frem i hierakiet (ligesom brugerens program selv kan).
Jeg er altså ikke interesseret i at dublere eller erstatte rodobjektet. Er det ikke det dit svar omhandler ?
Det skal bruges til at realisere en fuld (delvis read-only) objektmodel til et program der ingen har i forvejen. Og jeg har derfor ofte brug for at "refreshe" hele objektmodellen (slet + genopbyg), med rodobjektet som eneste undtagelse. Rodobjektet er dermed det eneste faste holdepunkt.
Det mit svar kan gøre er, at du kan have reference til klassen selv (rod klassen) i f.eks. et modul. Det kræver at dit klasse hierarki ligger i ét projekt. Du kan så erklære en Public variabel i modulet Public g_Application As Application, i class_initialize() bruger du så :
Set f_Apllication = Me
Så kan alle klasser i hierarkiet tage fat i rod objektet, igennem modulet.
Det er jo sådan set det jeg har forsøgt (se i toppen).
Fra modulet: Public g_objMIPro As Object Public g_Application As Application
Fra klassens kode: Private Sub Class_Initialize() Set g_objMIPro = GetObject(, "MapInfo.Application") If g_objMIPro Is Nothing Then Set g_objMIPro = CreateObject("MapInfo.Application") End If If g_objMIPro Is Nothing Then Exit Sub End If
Set g_Application = Me
strLastWorkspace = ""
'build/initialize object model Refresh End Sub
Og det virker tilsyneladende ikke. Når jeg tilgår g_Application fra en anden klasseinstans (dvs. under Refresh) får jeg den fejlmeddelelse jeg beskrev i problemoplægget.
Hvordan instantierer du din rod-class fra klient programmet:
Dim obj As Application Set obj = new Application
eller
Dim obj As New Application.
Det er den første du skal bruge. Denne skal du i øvrigt bruge hver gang du instantierer en klasse i dit projektet. Ellers risikerer du, at Class_Initialize() i rod klassen ikke er 'kørt' når du tilgår et af under objekterne.
Hej Kenneth, Undskyld fordi det tog så lang tid. Jeg skulle lige starte på et nyt job, samt starte mit eget konsulentfirma, og det tog en masse tid.
Det er altid svært at indrømme brølere, men det gør jeg altså. Efter nøje gennemgang af koden, med dine kommentarer in mente, så må jeg konstarere at fejlen faktisk slet ikke ligger hvor jeg troede, men et andet sted.
Du får naturligvis pointene, men jeg brygger snarest et nyt spørgsmål sammen (som jeg håber løser mit problem), og jeg håber meget du også vil lægge billet ind dér :-)
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.