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 PropertyMOI 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 PropertyLoistavaa, 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.