Results 1 to 7 of 7

Thread: Collections without methods!

  1. #1

    Thread Starter
    Addicted Member S@NSIS's Avatar
    Join Date
    Aug 2000
    Location
    Stoke-On-Trent, England
    Posts
    243
    found an example!!

    Take the Drives collection of the FileSystemObject. It is a collection of the Drive object and yet this Drives collection has no add,remove methods only Count and Item properties. In other words it is read-only and you can go:
    Code:
    For each Drive in Drives
     msgbox Drive.AvailableSpace
    Next
    This is how I want to able to make my collection. (no add or remove method)

    Thanks in advance

    Shaun
    Web/Application Developer
    VB6 Ent (SP5), Win 2000,SQL Server 2000

  2. #2
    Hyperactive Member
    Join Date
    Jun 2000
    Location
    Auckland, NZ
    Posts
    411

    No Static Methods

    As far as I am aware there is no implementation in VB for Class Static Methods. The example you gave is invalid because Drives is an instance of a collection object.

    Otherwise the For..Each loop would not work on it.

    When you are in a class module programming, you are really programming for an instance of the class. In otherwords, the only way to make any of your code function is to create an object of your class.

    In C++, Java and others, you can have static methods of a class which means you do not have to have an instance of the class in order to execute some of your code. In VB I think you are going to have to put up with the limitation.

    It's not such a big problem though as long as your class name is something like "clsContact" and you simply have a global variable in your code called "Contacts". Then you will get the exact duplicate of how the Drives collection in your example works. Don't forget to create the instanciate your global variable of course.

    Code:
    ' in a module or if it is only to be used in the form, in the form declaration area
    Public Contacts as clsContact
    
    ...
    
    ' in the Form_Load or Sub_Main
    Set Contacts =  New clsContact
    One more hint: When naming classes, try to use the singular form of the noun. Save plurals like "Contacts" for naming collections and so on.

    Regards

    P.S. I have just re-read everything and realise I have waffled on about something you no doubt know and more importantly, I didn't help towards your question. But I will leave the post in case it helps future readers...
    More to follow


    [Edited by PaulLewis on 09-18-2000 at 08:06 PM]
    Paul Lewis

  3. #3
    Hyperactive Member
    Join Date
    Jun 2000
    Location
    Auckland, NZ
    Posts
    411
    Code for the class and a test form to partially emulate a Collection. The fact that the For..Each loop can be used on an array or a collection (not UDT's of course) means you can do this.

    Hopefully it gives you a new direction to look at.


    Code:
    ' Class1 Class
    Option Explicit
    
    Dim mCol As Collection
    Dim mCol2() As String
    Dim mCount As Integer
    
    Private Sub Class_Initialize()
      Set mCol = New Collection
    End Sub
    
    Public Static Sub AddItem(anItem As String)
      ' adding an item adds to both forms of collection
      mCol.Add anItem
      mCount = mCount + 1
      ReDim Preserve mCol2(1 To mCount)
      mCol2(mCount) = anItem
      
    End Sub
    
    Public Static Function GetCol() As Collection
      ' example of getting the collection
      ' problem is that you get the add/remove methods too
      ' which is fair enough as it is a collection
      Set GetCol = mCol
    End Function
    
    Public Static Function GetCol2() As String()
      ' example of getting to the data but it is not a collection
      ' you will have to implement your own equivalent functions
      ' in your Class to provide what a collection does
      GetCol2 = mCol2()
    End Function
    Code:
    Option Explicit
    Dim myobj As Class1
    
    
    Private Sub Form_Load()
      Dim item As Variant
      
      Set myobj = New Class1
      myobj.AddItem "1"
      myobj.AddItem "2"
      Debug.Print
      Debug.Print
      
      ' looks similar
      With myobj
        For Each item In GetCol2
          Debug.Print item
        Next
      End With
    End Sub
    Paul Lewis

  4. #4

    Thread Starter
    Addicted Member S@NSIS's Avatar
    Join Date
    Aug 2000
    Location
    Stoke-On-Trent, England
    Posts
    243
    Cheers Paul,
    Funny actually, my classes are named clsContact (for an individuals) and my collection class is called (funnily enough) clsContacts.

    I guess that there isn't a way of doing it through VB as you said yourself
    ' example of getting the collection
    ' problem is that you get the add/remove methods too
    ' which is fair enough as it is a collection
    which is what I am trying to avoid!

    I don't think the Drives example is an invalid example because
    A: It is a collection (or so the object browser tells me)
    B: It doesn't have Add or Remove methods which collections are supposed to have.

    I did consider the array way of doing it (more work) as you suggested and it does seem that this is the way that I will have to go!

    Oh well, thanks for the pointers

    Cheers

    Shaun
    Web/Application Developer
    VB6 Ent (SP5), Win 2000,SQL Server 2000

  5. #5

    Thread Starter
    Addicted Member S@NSIS's Avatar
    Join Date
    Aug 2000
    Location
    Stoke-On-Trent, England
    Posts
    243

    Thumbs up

    Ps. I am no expert on this class OOP stuff yet although I hope to be getting there!

    So..If it helps, here is the code from the clsContacts object.

    Code:
    Option Explicit
    Private mContact As New clsContact 'Set an instance of the clsContact object
    Private mcol_Contacts As Collection
    Private mcolPointer As Long
    
    Private Sub Class_Initialize()
        Set mcol_Contacts = New Collection
        'Populate mcol_Contacts collection with clsContact objects whose properties are set
        'by a call to the database
        Set mcol_Contacts = PopulateContacts
        If mcol_Contacts.Count > 0 Then
            'Set mContact to be equal to the first item in our collection
            Set mContact = mcol_Contacts.Item(1)
            mcolPointer = 1 'Points to first item
        Else
            mcolPointer = 0 'No items to point to
        End If
    End Sub
    
    Public Function Add(ByVal NewContact As clsContact) As clsContact
        'Add the new contact to the mcol_Contacts collection
        mcol_Contacts.Add NewContact
        Set Add = NewContact
        'Set the pointer to point at the latest record added
        mcolPointer = mcol_Contacts.Count
        'Set the mContact object to have the properties of the latest object added
        Call ReloadMembers(NewContact)
    End Function
    
    Public Property Get Contact() As clsContact
        'Set the property equal to the current mContact object in use
        Set Contact = mContact
    End Property
    
    Private Sub ReloadMembers(aContact As clsContact)
    'Set the mContact object equal to aContact
    Set mContact = aContact
    End Sub
    
    Public Sub MoveFirst()
        'Set mContact to be equal to the first object in the collection
        Set mContact = mcol_Contacts.Item(1)
    End Sub
    Public Sub MoveLast()
        'Set mContact to be equal to the last object in the collection
        Set mContact = mcol_Contacts.Item(mcol_Contacts.Count)
    End Sub
    Public Sub MovePrevious()
        'Check to see if we are not already at the start of the collection and if not then move one object back in
        'the collection
        If mcolPointer > 1 Then
            mcolPointer = mcolPointer - 1
            Set mContact = mcol_Contacts.Item(mcolPointer)
        End If
    End Sub
    Public Sub MoveNext()
        'check to see if we are not already at the last object in the collection and if not then move
        'one object forward in the collection
        If mcolPointer < mcol_Contacts.Count Then
            mcolPointer = mcolPointer + 1
            Set mContact = mcol_Contacts.Item(mcolPointer)
        End If
    End Sub
    Public Property Get Count() As Long
        Count = mcol_Contacts.Count
    End Property
    
    Public Property Get AllContacts() As Collection
        'Return the collection
        Set allContacts = mcol_Contacts
    End Property
    Any thoughts or comments wil be appreciated!!

    Cheers

    Shaun
    Web/Application Developer
    VB6 Ent (SP5), Win 2000,SQL Server 2000

  6. #6
    Hyperactive Member
    Join Date
    Jun 2000
    Location
    Auckland, NZ
    Posts
    411

    Hmmm

    In tat case, I imagine that when writing for a dll in C++, you can mask certain inherited behaviour of a Collection such as in your example.

    At least though we agree that your example "Drives" is a collection. Now all that remains is to see if what you want to do can be achieved...

    If I discover anything I'll drop you a line.

    regards
    Paul Lewis

  7. #7
    Hyperactive Member
    Join Date
    Jun 2000
    Location
    Auckland, NZ
    Posts
    411

    OK, Here is another answer

    Thanks for posting the question because it has encouraged me to research a topic I have not bothered too much with in the past.

    I have produced the following code in my test application. This is ALL the code there is. Of course, there is an activeX DLL I wrote which provides the classes.

    Code:
    Option Explicit
    Dim myWheel As clsWheel
    Private Sub Command1_Click()
      Set myWheel = New clsWheel
      Dim spoke As clsSpoke
      
      With myWheel
        For Each spoke In .Spokes
          Debug.Print spoke.Name, spoke.Number
        Next
      End With
    End Sub
    I used examples from the Programmers manual (hence Wheel, Spokes, Spoke). Look for Creating Your Own Collection Classes.

    The myWheel.Spokes collection displays ONLY the count and Item methods exactly as you want. Object Browser displays only these methods as well.

    The code for the classes is below. There are a few things you need to do using the Tools | Procedure Attributes |Advanced menu but I can tell you those after the code if you need.

    Code:
    ' note that these are the class files 
    VERSION 1.0 CLASS
    BEGIN
      MultiUse = -1  'True
      Persistable = 0  'NotPersistable
      DataBindingBehavior = 0  'vbNone
      DataSourceBehavior  = 0  'vbNone
      MTSTransactionMode  = 0  'NotAnMTSObject
    END
    Attribute VB_Name = "clsSpoke"
    Attribute VB_GlobalNameSpace = False
    Attribute VB_Creatable = False
    Attribute VB_PredeclaredId = False
    Attribute VB_Exposed = True
    Option Explicit
    
    Dim mNum As Integer
    Dim mName As String
    
    Public Property Let Name(newName As String)
      mName = newName
    End Property
    Public Property Get Name() As String
    Attribute Name.VB_UserMemId = 0
      Name = mName
    End Property
    
    Public Property Let Number(newNum As Integer)
      mNum = newNum
    End Property
    Public Property Get Number() As Integer
      Number = mNum
    End Property
    
    
    VERSION 1.0 CLASS
    BEGIN
      MultiUse = -1  'True
      Persistable = 0  'NotPersistable
      DataBindingBehavior = 0  'vbNone
      DataSourceBehavior  = 0  'vbNone
      MTSTransactionMode  = 0  'NotAnMTSObject
    END
    Attribute VB_Name = "clsWheel"
    Attribute VB_GlobalNameSpace = False
    Attribute VB_Creatable = True
    Attribute VB_PredeclaredId = False
    Attribute VB_Exposed = True
    Option Explicit
    
    Dim mSpokes As clsSpokes
    Dim mShape As Integer
    
    Public Property Get Spokes() As clsSpokes
      Set Spokes = mSpokes
    End Property
    
    Public Property Get Shape() As Integer
      Shape = mShape
    End Property
    Public Property Let Shape(newShape As Integer)
      mShape = newShape
    End Property
    
    Private Sub Class_Initialize()
      Set mSpokes = New clsSpokes
    End Sub
    
    
    
    VERSION 1.0 CLASS
    BEGIN
      MultiUse = -1  'True
      Persistable = 0  'NotPersistable
      DataBindingBehavior = 0  'vbNone
      DataSourceBehavior  = 0  'vbNone
      MTSTransactionMode  = 0  'NotAnMTSObject
    END
    Attribute VB_Name = "clsSpokes"
    Attribute VB_GlobalNameSpace = False
    Attribute VB_Creatable = False
    Attribute VB_PredeclaredId = False
    Attribute VB_Exposed = True
    Option Explicit
    Private mcol As Collection
    
    Public Function NewEnum() As IUnknown
    Attribute NewEnum.VB_UserMemId = -4
    Attribute NewEnum.VB_MemberFlags = "40"
       Set NewEnum = mcol.[_NewEnum]
    End Function
    
    Public Property Get Count() As Integer
      Count = mcol.Count
    End Property
    
    Private Sub Class_Initialize()
      Set mcol = New Collection
      Dim spoke As clsSpoke
      
      Dim c As Integer
      
      For c = 1 To 10
        Set spoke = New clsSpoke
        
        With spoke
          .Name = "Spoke" & c
          .Number = c
        End With
        
        mcol.Add spoke, "Item " & Str(c)
      Next
    End Sub
    
    Public Function Item(ByVal Index As Variant) As clsSpoke
    Attribute Item.VB_UserMemId = 0
       Set Item = mcol.Item(Index)
    End Function
    Note that to use these classes you should copy them into files directly and not attempt to paste them into the VB IDE.

    I hope it makes sense. The VB documentation on this topic is excellent so if you get stuck, ask me or see if your documentation helps too

    Cheers
    Paul Lewis

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width