Osaisiko joku neuvoa miten VBA:ssa asetetaan luokan ominaisuudeksi toinen luokka? Ja ennen kaikkea: miten tästä luokkaominaisuudesta saadaan tietoja ulos ja miten siihen tallennetaan tietoa?
Pitääkö ominaisuutena oleva luokka instantioida ylemmän luokan konstruktorissa?
Tässä opastus luokkien käytöstä VBA:ssa
Kiitos.. olen kyllä tutustunut kyseiseen dokumenttiin (ja lukuisiin muihin googlella löytyviin) ja se ei sisällä tietoja jotka vastaisivat kysymykseeni. Eli lisävihjeitä kaivataan.
Moi OttoChorin!
kyllähän luokan saa VBA:ssa toisen luokan ominaisuudeksi...
'UserForm1 Private cl1 As Class1 Private cl2 As Class2 Private Sub CommandButton1_Click() Select Case CommandButton1.Caption Case "CommandButton1" Set cl1 = New Class1 cl1.myvar = 1 Set cl2 = New Class2 Set cl2.myclass = cl1 Set cl1 = Nothing CommandButton1.Caption = "CommandButton2" Exit Sub Case "CommandButton2" If Not cl2 Is Nothing Then MsgBox "Luokan Class2 instanssin cl2 ominaisuuden myclass sisältämän objektin " + Chr(34) + "cl1" + Chr(34) + " ominaisuuteen myvar asetettu arvo: " & cl2.myclass.myvar cl2.myclass.myvar = Chr(34) + CStr(2) + Chr(34) CommandButton1.Caption = "CommandButton3" Exit Sub End If Case "CommandButton3" If Not cl2 Is Nothing Then MsgBox "Luokan Class2 instanssin cl2 ominaisuuden myclass sisältämän objektin " + Chr(34) + "cl1" + Chr(34) + " ominaisuuteen myvar asetettu uusi arvo: " & cl2.myclass.myvar CommandButton1.Caption = "CommandButton1" Set cl2 = Nothing End If End Select End Sub
'Class1 Private var As Variant Public Property Get myvar() As Variant myvar = var End Property Public Property Let myvar(value As Variant) var = value End Property
'Class2 Private newclass As Object Public Property Get myclass() As Object Set myclass = newclass End Property Public Property Set myclass(cl As Object) Set newclass = cl End Property
Kiitoksia hyvästä koodiesimerkistä.
Mitenkäs tämä nyt sitten menee jos haluaisi "yläluokan" ominaisuudeksi suoraan jonkin luokan, siis ei object-tyyppistä oliota johon muualla koodissa luotu ilmentymä "alaluokasta" sijoitetaan..?
Ilmeisesti ominaisuutena olevasta luokasta on luotava ilmentymä "yläluokan" class_initialize-metodissa? Miten Property let:iä ja property get:iä käytetään kun halutaan päästä käsiksi ominaisuutena olevan luokan tietoihin?
Ei ainakaan seuraavaan tapaan:
'----Isäntäluokka----' Private Child(1 To 2) As ClassMember Sub class_initialize() Set Child(1) = New ClassMember Set Child(2) = New ClassMember End Sub Property Let Rate(Member As Integer, row As Integer, col As Integer, value As Integer) Child(Member).Table(row, col) = Rate End Property Property Get Rate(Member As Integer, row As Integer, col As Integer) Rate = Child(Member).Table(row, col) End Property
'----ominaisuusluokka----' Private pTable(1 To 5, 1 To 5) As Integer Property Let Table(row As Integer, col As Integer, value As Integer) If row < 1 Or row > 5 Or col < 1 Or col > 5 Then MsgBox "Error!" Exit Property End If pTable(row, col) = value End Property Property Get Table(row As Integer, col As Integer) If row < 1 Or row > 5 Or col < 1 Or col > 5 Then MsgBox "Error!" Exit Property End If Table = pTable(row, col) End Property
MOI taas OttoChorin!
SIIS ASIA ON NIIN...ettei luokkaa voi sijoittaa jonkin toisen luokan ominaisuudeksi ilman, että luokka sijoitetaan Object muuttujaan, koska LUOKKA ON OBJEKTI!!!
'Missä tämä 'ClassMember' on määritelty ja miksi?
Private Child(1 To 2) As ClassMember
'Elikäs kun käytetään SET-metodia niin käsitellään objektia
Set Child(1) = New ClassMember
'...
SUOSITTELEN TUTUSTUMAAN TEOKSEEN: Microsoft Visual Basic 6.0 Ohelmoijan käsikirja (Microsoft Press ISBN 951-826-030-3) ja eritoten kirjan Lukuun 9 Ohjelmointi objekteilla (alkaa sivulta 481)
Ylläolevassa "esimerkissä" ClassMember-luokan koodi on tuossa alemmassa boksissa, joka alkaa kommentilla
'----ominaisuusluokka----'
Pahoittelen epäselvää merkintätapaani, asiaa oli varmasti vaikea ymmärtää tämän vuoksi.
Haluaisin siis saada olion ominaisuudeksi toisen olion.. siten että kun olio instantioidaan, tulee ominaisuusolio sen ominaisuudeksi ilman sen kummempia kommervenkkejä. Kuvittelisin että tämä on VB:ssa / VBA:ssa mahdollista.
Esimerkiksi Javassa tämä käy helposti.
Ymmärrän kyllä mitä set-lause tekee.
Valitettavasti "Microsoft Visual Basic 6.0 Ohelmoijan käsikirja" ei sisällä tietoja kysymästäni asiasta tai minä olen kyvytön niitä sieltä löytämään, muuten en olisi täällä foorumilla asiaa kyselemässä.
Kiitos jo saamistani ohjeista! Ehkä asia vielä selviää.
EDIT:
Havaitsen että jos luokkaominaisuus on "public" sen saa helposti toisen luokan ominaisuudeksi esittelemällä sen ominaisuutena new-avainsanaa käyttäen niin kuin oliot yleensä.
Kysymys on nyt oikeastaan siitä, miten luokka-ominaisuuden, jonka julkisuusaste on "private", tietoihin päästään käsiksi. Tämä ei ole oikein kokeilemalla auennut.
Alan kyllä pikkuhiljaa kyseenalaistamaan koko pyrkimyksen mielekkyyttä, koska miksipäs ominaisuusluokka ei voisi olla "public" jos sen omat ominaisuudet sitten ovat "privateja".
Moi taas OttoChorin!
That's the way to do it...
'UserForm1 Private ClMain As New ClassMain Private Sub CommandButton1_Click() 'Testi... ClMain.Rate(1, 1, 1) = 1 MsgBox ClMain.Rate(1, 1, 1) ClMain.Rate(2, 1, 1) = 2 MsgBox ClMain.Rate(2, 1, 1) On Error Resume Next ClMain.Rate(3, 1, 1) = 3 MsgBox ClMain.Rate(3, 1, 1) If Err <> 0 Then Err.Clear On Error GoTo 0 End If End Sub
'ClassMain (Instancing: 1 - Private) Dim Child() As ClassMember Private Sub class_initialize() ReDim Child(1 To 2) As ClassMember Set Child(1) = New ClassMember Set Child(2) = New ClassMember End Sub Property Let Rate(theMember As Integer, theRow As Integer, theCol As Integer, theValue As Integer) Child(theMember).Table(theRow, theCol) = theValue End Property Property Get Rate(theMember As Integer, theRow As Integer, theCol As Integer) As Integer Rate = Child(theMember).Table(theRow, theCol) End Property Sub IncreaseBounds() ReDim Preserve Child(1 To UBound(Child) + 1) As ClassMember Set Child(UBound(Child)) = New ClassMember End Sub Sub DecreaseBounds() If UBound(Child) > 2 Then Set Child(UBound(Child)) = Nothing ReDim Preserve Child(1 To UBound(Child) - 1) As ClassMember End If End Sub
'ClassMember (Instancing: 1 - Private) Private pTable(1 To 5, 1 To 5) As Integer Property Let Table(row As Integer, col As Integer, value As Integer) If row < LBound(pTable, 1) Or row > UBound(pTable, 1) _ Or col < LBound(pTable, 2) Or col > UBound(pTable, 2) Then MsgBox "Error!" Exit Property End If pTable(row, col) = value End Property Property Get Table(row As Integer, col As Integer) As Integer If row < LBound(pTable, 1) Or row > UBound(pTable, 1) _ Or col < LBound(pTable, 2) Or col > UBound(pTable, 2) Then MsgBox "Error!" Exit Property End If Table = pTable(row, col) End Property
Loistavaa, tämä selvitti asian hyvin. Kiitoksia.
Sellainen asia on vielä hämärän peitossa, että miten luokan ominaisuutena voisi olla objektien taulukko, jonka ominaisuutena jälleen voisi olla objektien taulukko.. ja että näihin ominaisuuksiin vielä pääsisi käsiksi.
VB/A:ssahan näyttää olevan niin, että taulukot eivät voi olla näkyvyydeltään "public" jos ne ovat luokkamoduuleissa. Siksi niiden tietoja pitäisi käsitellä property let- ja property get-lauseilla, mutta (?) tämä onnistuu vain yhden objektihierarkian tason yli.
Nean yllä kuvaama tapa toimii luontevasti jos objektihierarkiassa on kaksi tasoa, mutta mitä tehdä kun tasoja on enemmän?
OttoChorin kirjoitti:
Siksi niiden tietoja pitäisi käsitellä property let- ja property get-lauseilla, mutta (?) tämä onnistuu vain yhden objektihierarkian tason yli.
Kyllä kutsuja pitäisi voida ketjuttaa:
olio.Table(5, 10).Table(2, 3).TeeJotain() ' Toiminnaltaan sama apumuuttujilla: a = olio.Table(5, 10) b = a.Table(2, 3) b.TeeJotain()
Moi taas OttoChorin!
Vähän Property-asiaa elikäs...
Property Let Table(row As Integer, col As Integer, value As Integer)
=
Sub AsetaArvo_Table(row As Integer, col As Integer, value As Integer)
ja
Property Get Table(row As Integer, col As Integer) As Integer
=
Function PalautaArvo_Table(row As Integer, col As Integer) As Integer
Osaisitteko sanoa allaolevasta tapauksesta miten "Tablen" (luokassa class3) tietoja käsiteltäisiin Class1:n ilmentymän kautta?
'---Module---' Sub TestClass1() Dim Obj1 As New Class1 Obj1.Obj2(5).Number(2, 3, 3) = 5 MsgBox Obj1.Obj2(5).Number(2, 3, 3) End Sub
'---class3---' Private pTable(5, 5) As Integer Property Get table(row As Integer, col As Integer) As Integer table = pTable(row, col) End Property Property Let table(row As Integer, col As Integer, value As Integer) pTable(row, col) = value End Property
'---class2---' Dim Obj3(5) As New Class3 Property Let Number(O3i As Integer, row As Integer, col As Integer, value As Integer) Obj3(O3i).table(row, col) = value End Property Property Get Number(O3i As Integer, row As Integer, col As Integer) As Integer Number = Obj3(O3i).table(row, col) End Property
'---class1---' Dim Obj2(5) As New Class2 Property Let Number(O2i As Integer, O3i As Integer, row As Integer, col As Integer, value As Integer) Obj2(O2i).Number(O3i, row, col) = value End Property Property Get Number() As Integer Number = Obj2(O2i).Number(O3i, row, col) End Property
Moi taas OttoChorin!
Another the way to do it...
'UserForm1 Private Sub CommandButton1_Click() TestClass1 End Sub
'Module1 Sub TestClass1() Dim Obj1 As New Class1 Obj1.AsetaArvo_Number 5, 2, 3, 3, 5 MsgBox Obj1.PalautaArvo_Number(5, 2, 3, 3) End Sub
'Class1 (Instancing: 1 - Private) Dim Obj2(5) As New Class2 Sub AsetaArvo_Number(O2i As Integer, O3i As Integer, row As Integer, col As Integer, value As Integer) Obj2(O2i).AsetaArvo_Number O3i, row, col, value End Sub Function PalautaArvo_Number(O2i As Integer, O3i As Integer, row As Integer, col As Integer) As Integer PalautaArvo_Number = Obj2(O2i).PalautaArvo_Number(O3i, row, col) End Function
'Class2 (Instancing: 1 - Private) Dim Obj3(5) As New Class3 Sub AsetaArvo_Number(O3i As Integer, row As Integer, col As Integer, value As Integer) Obj3(O3i).AsetaArvo_table row, col, value End Sub Function PalautaArvo_Number(O3i As Integer, row As Integer, col As Integer) As Integer PalautaArvo_Number = Obj3(O3i).PalautaArvo_table(row, col) End Function
'Class3 (Instancing: 1 - Private) Private pTable(5, 5) As Integer Function PalautaArvo_table(row As Integer, col As Integer) As Integer PalautaArvo_table = pTable(row, col) End Function Sub AsetaArvo_table(row As Integer, col As Integer, value As Integer) pTable(row, col) = value End Sub
Aihe on jo aika vanha, joten et voi enää vastata siihen.