Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: VBA / sisäkkäiset luokat (eli luokka toisen luokan ominaisuutena)

Sivun loppuun

Otto Chorin [09.09.2010 11:20:12]

#

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?

groovyb [09.09.2010 12:04:46]

#

Tässä opastus luokkien käytöstä VBA:ssa

http://www.cpearson.com/excel/Classes.aspx

Otto Chorin [09.09.2010 12:31:07]

#

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.

neau33 [09.09.2010 13:57:59]

#

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

Otto Chorin [10.09.2010 11:15:01]

#

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

neau33 [10.09.2010 14:17:10]

#

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)

Otto Chorin [13.09.2010 11:21:32]

#

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".

neau33 [13.09.2010 14:09:40]

#

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

Otto Chorin [14.09.2010 11:48:29]

#

Loistavaa, tämä selvitti asian hyvin. Kiitoksia.

Otto Chorin [15.09.2010 11:21:57]

#

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?

Metabolix [15.09.2010 12:35:46]

#

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()

neau33 [16.09.2010 10:41:08]

#

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

Otto Chorin [16.09.2010 11:04:51]

#

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

neau33 [16.09.2010 14:11:57]

#

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

Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta