Extending a class - am I doing this right?

I have a collection of items which I want to reference by their names - as it might be “ball”, “bat”, “stick”, etc. So a dictionary suggests itself. Now for each of these items, there are two integer properties, let’s say count1 and count2. The question is how to represent all this.

I tried making a new class (say, myitems) whose super is dictionary, and then adding two properties to it, count1 and count2. But having created the class, I couldn’t figure out how to use it, or if indeed it is possible. I tried such as:

  dim mydict as new myitems
  mydict.value("bat").count1 = 27
  mydict.value("bat").count2 = 44

but the compiler rejected this. Is this the right approach but wrong syntax, somehow?

I’m also looking at just using a plain dictionary, and making a new class (say, myvals) with two properties, count1 and count2. Then I’d be doing:

  dim mydict as new dictionary, vals as new myvals    // Initialisation done somewhere in my code
  vals.count1 = 27
  vals.count2 = 44
  mydict.value("bat") = vals

I’d prefer the former (if possible) since there is a requirement for count1 and count2 to be updated from time to time. I’d like to avoid doing the following:

  dim mydict as new dictionary, vals as new myvals    // Updating done elsewhere in my code
  vals = mydict.value("bat")
  vals.count1 = vals.count1 + 3
  vals.count2 = vals.count2 - 7
  mydict.value("bat") = vals

which seems rather heavy. Much better if I could say:

   mydict.value("bat").count1 = mydict.value("bat").count1 + 3
   mydict.value("bat").count2 = mydict.value("bat").count2 - 7

Or should I be using a different approach entirely?

That’s basically the right thing to do. You can also introduce a custom dictionary class that provides an API for updating those count1 and count2 properties. Your code:

 mydict.value("bat").count1 = mydict.value("bat").count1 + 3

just doesn’t work because the compiler can’t verify that the contents of the “bat”-item is a myvals-object. So

 myvals(mydict.value("bat")).count1 = myvals (mydict.value("bat")).count1 + 3

should work, but is ugly enough to warrant the introduction of a new class that hides this stuff.

Ah.

That rings a bell. Should I be creating a method that defines what “+” means in this context? I seem to remember reading something somewhere in the docs about doing that.

I usually stay away from these Operator methods for a very particular reason - when you debug them you suddenly have to remember to hit “step into” at a line looking like this:

myObject=myObject+6

But then again, that’s just me. It also might not be possible given that your add method also needs to know which myVals-Object it needs to act on.

I just found Operator_Add and suspect that this is not what I need. I need to figure out how to specify the properties I’ve added. Neither of these does it:

mydict.value("bat").count1 = 27 mydict.count1.value("bat") = 27

Casting as you describe satisfies the compiler but I can’t see how to define the class such that the casting is not needed.

Cast the object returned from the dictionary

Something like this? (untested)

Myvals(mydict.value("bat")).count1 = Myvals(mydict.value("bat")).count1  + 3

Or add an AddToCount1 (v as variant) method to the class

Myvals(mydict.value("bat")).AddToCount1(3)

Looks like what Maximilian was also suggesting. Yes, that keeps the compiler happy. I haven’t actually executed it yet :slight_smile:

or create your own custom subclass of dictionary that is ONLY for holding this custom class and make it always return a properly casted value
write that code once and be done with it

class MyValDict
    function value(key as variant) as MyVals
            return Myvals(mInternaldict.value(key))
    end function

   Sub value(key as variant, assigns value as MyVals)
            mInternaldict.value(key) = value
    end function

   Sub Constructor()
        mInternalDict = new Dictionary
    end sub

   private mInternalDict as Dictionary
end class

[quote=246323:@Jeff Tullin]Cast the object returned from the dictionary

Something like this? (untested)

Myvals(mydict.value("bat")).count1 = Myvals(mydict.value("bat")).count1  + 3

This keeps the compiler happy but at runtime I get:

[quote=246302:@Tim Streater]I’d prefer the former (if possible) since there is a requirement for count1 and count2 to be updated from time to time. I’d like to avoid doing the following:

  dim mydict as new dictionary, vals as new myvals    // Updating done elsewhere in my code
  vals = mydict.value("bat")
  vals.count1 = vals.count1 + 3
  vals.count2 = vals.count2 - 7
  mydict.value("bat") = vals

[/quote]
That last line isn’t necessary. vals is a reference to the object stored in the dictionary. You are updating its values directly, you don’t need to set it back to the dictionary. This is really the best way to go with variants - use a temp variable and avoid casting.

dim vals an myvals   // new is not required either
vals = mydict.value("bat")
vals.count1 = vals.count1 + 3
vals.count2 = vals.count2 - 7

I had a thought earlier, though. Aren’t count1 and count2 properties of the entire dictionary, rather than there being a count1 and count2 for each dictionary entry?

For the moment, in order to keep going, I’m using two dictionaries rather than a subclass. But I am still keen on the subclass :slight_smile:

No. Count1 and Count2 are properties of the object that this one entry in the dictionary points to. Each dictionary entry is a separate myvals object, which has its own count1 and count2 value.

Yes I see that - I was more thinking of my original desire (see OP) to be able to extend the dictionary class in order to be able to directly write:

  dim mydict as new myitems
  mydict.value("bat").count1 = 27
  mydict.value("bat").count2 = 44

which seems not possible. But I’m OK with what you have proposed.

Thanks all.

  dim mydict as new myitems
  mydict.value("bat") <<< this method returns an object. 

“count1” is a property on whatever object is returned
not a property of the dictionary