Inheritence of encapsulated arrays using OOP

BlitzMax Forums/BlitzMax Beginners Area/Inheritence of encapsulated arrays using OOP

GreenVertical(Posted 2014) [#1]
Hi I'm trying to do a program in OOP style and am struggling how to properly have inheritance of an encapsulated array.

I want to have a number of declared Types which each have arrays encapsulated in them.
I can do this for one parent Type but unfortunately the array method doesn't inherit properly to the child objects.

I can perfectly understand why my code isn't working as intended: I have to specify the parent Type class in the method of creating the array. However I don't know how else to do it.
It seems rather inefficient for me to have to repeat essentially the same dimArray method for every inherited Type to avoid the problem I'm having.

Is there a more 'abstract' way of setting up an encapsulated array which allows for inheritance?

Here is an example which illustrates what I am trying to do and what won't work.
Thanks in advance
GreenVertical




Brucey(Posted 2014) [#2]
Print "child obj 1: " + tAChild.array[1].a
Print "parent obj 1 {again}: " + tAParent.array[1].a

You realise that your array is Global, so there is a single instance of the array the type, rather than one each for the objects?

So this :
tAChild.array[1].a= 456

will change the value in the global array.

Do you want a static/global array, or do you want an array that exists per object?

Or, do you want a separate global array each for the parent and child types?
Type TchildObj Extends TparentObj
	Global Array:TParentObj[]
...


I think perhaps you are misunderstanding the relationships in the hierarchy.


Yasha(Posted 2014) [#3]
There are what look like two problems with what you're trying to do here:

1) .array is global. That means the name links to one location per program, not per access point or whatever. TchildObj.array and TparentObj.array are the same location, and cannot be made to point to different places, because the only way TchildObj has an .array member at all is by inheritance of the one that already exists.

2) .array has the wrong type: it is typed as containing only TparentObj instances, and while you could still put TchildObj instances into it (because of subtyping), a. you aren't doing that (dimArray only calls New TparentObj), and b. it's not possible to access fields of the contents of an array that the array itself isn't aware of; if it did contain TchildObj instances, you'd have to downcast them from TparentObj before you could access field .p. All the compiler sees is you trying to access .p on a TparentObj.

To address the first issue, yes you will have to duplicate some typing to create a new array for TchildObj (but given that you're creating a new array slot, not reusing the old one, this seems fair). You can redesign dimArray to take a "destination" Var to write to, to share code, or something similar (perhaps a factory object would look better?).

To address the second issue (part 1) - that the same code is always creating objects of the same type - you can take advantage of a little-known Max feature: if you call New with an object as the parameter rather than a type name, it will duplicate that object without knowing what it is (i.e. it can dynamically create objects of different types), so you can "seed" dimArray with a base object to copy into the array rather than a hardcoded type.

There is no way to address the second issue (part 2) - BlitzMax's type system is not sophisticated enough to express this statically. You need to use a downcast if you want to access fields of a subtype of the array's element type (although depending on how you solve the first two issues, this one may stop being relevant anyway).


The simpler solution that looks like it's closer to what you mean to do, is to not keep your instance fields and your global management arrays in the same type at all. Instead of making .array global and a part of this type at all, you could make it an instance field of a separate manager type. That will give you a small number of arrays - as many as you choose to instantiate of the manager type - without needing to use Globals, which restrict you to exactly one.


GreenVertical(Posted 2014) [#4]
Thanks to Brucey and Yasha. I am starting to realise how complicated and difficult OOP is. it sounds like I need to use a separate manager type. I'll try and post the code for others' benefit when/if I manage to solve it.