Reputation: 15807
I understand that the class Object is at the top of the class hiearchy in an Object Oriented programming langauge, like Java. I also understand that you have reference types and value types in .NET. I also understand type definitions in C based languages.
Despite this; I am struggling to understand what an Object is in VB6( http://msdn.microsoft.com/en-us/library/aa338034%28v=vs.60%29.aspx ) and what exactly a variant is. What is a variant? and how is an object implemented in VB6?
Upvotes: 7
Views: 5344
Reputation: 5689
All objects used by VB6 are COM objects. A COM object is essentially a variable length data structure whose variable length header contains any number of 32 bit pointers to VTables, and sucessive bytes contain the instance data of the object. For instance,
Bytes
0-3 VTable1 pointer
4-7 VTable2 pointer
8-11 VTable3 pointer
...
Instance data
A VTable is an array of 32 bit pointers to functions which all are passed a "this" instance pointer.
Bytes
0-3 Func1(this, ..., ...)
4-7 Func2(this, ..., ...)
8-11 Func3(this, ..., ...)
...
The only other specification is that all VTables MUST inherit from IUnknown, i.e. the first three functions must be:
QueryInterface()
AddRef()
Release()
Essentially, QueryInterface() allows you to find out whether a COM object supports a specific interface (which is represented by an UUID). AddRef() allows the object writer to increment an internal reference count. Release() allows the object writer to decrement the reference counter, destroying the object when the count is zero. You never call these methods in VB - the compiler adds these calls for you (one of the advantages of VB6).
See http://msdn.microsoft.com/en-us/library/windows/desktop/ms680509(v=vs.85).aspx for more details.
A VB 'Object' type is a reference to an object which supports the IDispatch interface (see http://msdn.microsoft.com/en-us/library/windows/desktop/dd318520(v=vs.85).aspx). This is what allows you to do late binding in VB and VBScript. All objects written in VB6 automatically implement an interface that inherits from IDispatch. This is called a dual interface, because it supports early and late binding.
Note that there is no direct type system built into COM. However, you can opt to support the ITypeInfo interface, which allows the users of your object to access the information you want to add about the object (it is easier to use the default implementation which uses type libraries to store this information).
The Variant type, as mentioned by Bob Riemersma, is actually a 16 byte structure which has a 2 byte integer (vt) which indicates what Automation type is being encapsulated, and the latter 8 bytes can be used to contain value types of up to 8 bytes, or a 32 bit pointer to another type. VB does all the necessary conversion between VB types and Variants using its internal functions, and all the necessary memory allocations and deallocations. Variants can contain references to COM objects by copying the pointer to the object into the Variant, and calling the object's AddRef() method.
Upvotes: 10
Reputation: 56735
Let me break this down into separate issues:
First, VB6 is not VB.Net and does not use the .Net Framework, but instead uses the older COM framework. (cannot tell if you already knew this).
Secondly, what your link is pointing to are really the Classes builtin to VB6. Even though, yes, it calls them "Objects". Sloppy terminology on their part.
Thirdly, and probably most importantly, in VB6, everything is not an Object, and Objects are not even the default or dominant category of data-type. What is, is something like the value-types of .Net, but a whole lot less (most did not even have run-time type-containers, just addresses in memory).
So most data items were not objects, thus did not have classes, so did not have inheritance of any kind, so were not derived from anything else, and so did not have a "type hierarchy" and so could not have had anything at "the top of" their type-hierarchy (though the things that were classes/objects did have all of this). And so, you had no base/root data type that you could use for any other data-type, which would have been a problem for all kinds of parameter-passing, etc., situations.
Variants were a sort of prior solution to this problem that in earlier versions of VB were implemented (earlier than Objects in VB) to address this problem. A Variant is just a dynamic-descriptor that wraps another item of any data-type. When you use it it (generally) acts like you are directly using what it contains, but you are really going through the Variant to get to whatever type of data item it currently happens to contain.
The Variant itself keeps track of what its content's data-type is, and causes the VB code accessing it to behave differently/appropriately (a primitive kind of polymorphism).
If this sounds like its kludgy and was a lot of overhead, well, it was. But at the time it was the best available solution when you needed to handle "any data-type".
Upvotes: 5