Object Arrays and Variants

Hello Everybody,

I have following issue:

Basically, I want to store arrays of distinct object types generically (so, in Variants) and retrieve them elsewhere into an Object array.
Firstly, if I cast an concrete array into an abstract one (i.e., in an Object array) and back, it won’t work, but if I store the abstract in a variant, then back, it works.
Secondly, the same thing upside-down - concrete into variant and then into abstract - is not working.

I hope following snippet shows, what I want to do:

  Dim concrete(), concreteBack() As Dictionary
  Dim abstract() As Object = concrete
  abstract.Append(new Dictionary("a" : "b"))
  'concreteBack = abstract 'this line won't compile
  Dim temp As Variant = abstract
  concreteBack = temp
  'abstract = temp 'this line raises an TypeMismatchException
  MsgBox(concrete(0).Value("a") + ", " + concreteBack(0).Value("a"))

Is there anyone who can explain me why the out commented lines are not working?
Or how I can tell the compiler, that in line 4 ‘abstract’ has the right type?

I have a workaround in mind, where i define a container which stores an object array and a variant, but i’d prefer it to manage ALL types in a single variant and this is, I believe, the idea behind variants.

Thank You,
Christopher

Why is it you want to use variants and dictionaries of them ?

Oh, and I’m not surprised that the dictionary - > variant & back has issues

The reason that variant works is that it does run-time type checking and the variables just happen to be the right type. The commented lines use compile-time type checking and they aren’t the right type of variables (although they could hold the right type, but you would have to cast the generic variable to the specific one, which I don’t know if there is a syntax for that that works with arrays).

Be careful with arrays and variants, however. You can get yourself twisted into knots very easily. What you’re trying to do will probably require introspection at some point.

There isn’t. You have to implicitly cast.

In general I avoid trying to use Xojo as a dynamically typed language
Interfaces, classes & subclasses make it so the compiler can help me out a lot more
With variants & such it can’t except somewhat superficially

Time to factor the design. What are you trying to accomplish?

Do you come from Visual Basic? If yes, then don’t try to work with Variant like you were used to. There are only very very few instances where you have to work with Variants in Xojo.

concrete is an array of dictionaries
abstract is an array of objects
… of course you can’t assign an array of dictionaries to a variable dimmed as array of objects and vice versa. You will have to fill the abstract array by looping over the concrete one and appending each element to abstract.

You can assign a dictionary array to object array, that’s upcasting. The other way, downcasting, needs a loop.

No you can’t. Casting of entire arrays in not supported in Xojo. You have to loop over the elements of the source array, cast each element and append it to the target array.

Yes, implicit upcasting of arrays work in Xojo

[code] dim a() As Dictionary
dim b() As Object

b = a //upcasting works
a = b //downcasting not[/code]

The down casting method I use relies on upcasting to the parameter type to make it generic

[code]

downcast(b, a)

Sub downCast(src() As Object, dest() As Object)
if src = nil or dest = nil then return
dim last As integer = src.Ubound
redim dest(last)
for i As integer = 0 to last
dest(i) = src(i)
next
End Sub[/code]

Didn’t know that. Since down casting an array is not possible, I never tested the opposite. Good to know, thank you!

That’s not casting. That’s simple assignment of compatible parameters.

Yeah, this is what actually confuses me. In most other languages I believe it is possible in both directions, and I also do not see the sense in restricting the downcast way…

@Beatrix Willius: actually, i come from C++, but worked with some other languages, including VB

I’m still curious what you even want to use this style of code for ?
Every time I run into this sort of thing I really have to examine it and rethink doing this in a type safe way usually using a class that is a strongly typed container type and some strongly typed element type (even if it uses interfaces which makes it more flexible)

Since there’s no STL in Xojo (too bad but we need generics for it) you have to make your own types but then you get type safety just like if you used STL in C++

I want to serialize objects, primitives and their array forms, transfer them via network and deserialize them. So I wrote something, that expects a Variant, examines its type, gets the value out of it, serzializes it and so on. It works for everything, even for primitive arrays, but not for object arrays.

I COULD make a super class, called ‘Serializable’ or something, but that would be overhead at multiple points

Or, the other way, is to use Object() arrays instead of distinct ones from beginning on, inserting my objects into them, store them in the variant and retrieve them as Object arrays. I think I will go this way now, since I do not have endless time for this project, but it is at first more intuitive and faster if you have a method like

Sub method(myObjects() As MyClass)
for each mo As MyClass In myObjects
 //go on
end for
End Sub

than this

Sub method(myObjects() As Object)
Dim mo As MyClass
for i As Integer to UBound(myObjects)
 mo = MyClass(myObjects(i))
end for
End Sub

AND you have to document it somewhere that you can (MUST) cast each object before you can use it.

And I still can’t get, why it is not possible to downcast. As far as I understood, array variables are references.
So, if I copy the reference to an array of a specific class to an array of a super class (yeah, it works for each superclass, not only for Objects), it implicitly converts it, and everything is fine.
That the compiler denounces the opposite direction, is apparantly correct, because variables (and array elements) of super classes are not necessarily instances of my specific subclass. So, with simple variables, Xojo kindly gives me the option to cast:

Dim foo As New MyClass Dim bar As Object = foo foo = MyClass(bar)
and I am happy. But this won’t work:

Dim foo() As New MyClass Dim bar() As Object = foo foo = MyClass()(bar) 'no foo = Array(MyClass)(bar) 'no foo = MyClasses(bar) 'no foo = IamSureThisIsAnArrayOfMyClasses(bar) 'no

The same exact thing, except they are no arrays, does not work, since Xojo has no syntax to cast arrays :frowning:

It would be a Class Interface. But it still doesn’t solve the problem. There really isn’t a good way to do generic serialization in a strongly typed language such as Xojo.

[quote=83948:@Christopher Kobusch]I want to serialize objects, primitives and their array forms, transfer them via network and deserialize them. So I wrote something, that expects a Variant, examines its type, gets the value out of it, serzializes it and so on. It works for everything, even for primitive arrays, but not for object arrays.

I COULD make a super class, called ‘Serializable’ or something, but that would be overhead at multiple points[/quote]
Thats what I’d do as then every object type you want to do this with implements the interface
But you’ll have to have every class you implement implement the interface as there really isn’t (seriously) a way to do a generic object serializer - really

Yeah, didn’t with everybody else, it really isn’t possible. When developing the first WE, I spent tried hard to find a generic way to serialize and unserialize any object. Even had some secret (evil) tricks at my disposal. Just wasn’t going to happen.

It’s a rabbit hole. You’ll solve one problem and create / discover two more. Stop while you’re ahead and use something like JSONItem instead.