How to cast to an extended type and access field?

BlitzMax Forums/BlitzMax Programming/How to cast to an extended type and access field?

ImaginaryHuman(Posted 2009) [#1]
I can't seem to figure out how to access the field "Vertices" after extending the type.... how is this supposed to work?

Type Shape
	Field Format:Int=0
End Type

Type ShapeFloat Extends Shape
	Field Vertices:Float Ptr=Null	
End Type

Type ShapeDouble Extends Shape
	Field Vertices:Double Ptr=Null				
End Type

Local ShapeToUse:Shape=New Shape
ShapeToUse.Format=0
If ShapeToUse.Format=0 Then ShapeToUse=ShapeFloat(ShapeToUse) Else ShapeToUse=ShapeDouble(ShapeToUse)
ShapeToUse.Vertices=Null			

It says the `Vertices` field is not defined?


plash(Posted 2009) [#2]
Umm.. ShapeToUse should be Null, given your code.


jpavel(Posted 2009) [#3]
You can only access fields present in the -declared type- of the object.
So things like this really have no effect,

ShapeToUse=ShapeFloat(ShapeToUse)

since the type of ShapeToUse is always just Shape.

You'd need to declare a new variable of type ShapeFloat or ShapeDouble to be able to access the Vertices field.


Jur(Posted 2009) [#4]
That behavior is a weak point of Blitzmaxs polymorphism (dontīt know if other languages are diferent in that regard). It force you to add fields and methods to the super class, even if they are used only in some of the extended classes. But this is only needed for the fields and methods which are called from the outside of the class.


N(Posted 2009) [#5]
That behavior is a weak point of Blitzmaxs polymorphism (dontīt know if other languages are diferent in that regard).
No, this is exactly how it should be...

It force you to add fields and methods to the super class, even if they are used only in some of the extended classes.
No, it doesn't. Consider this, both subclasses have a vertices field, so both should have a SetVertices method. This should be a pure-virtual method in the base class and be implemented by the subclasses.

If anything, the above is just plain bad design.


Czar Flavius(Posted 2009) [#6]
Make GetVertices an abstract method of shape, which always (has to) return a double, but then at least you could have vertices as either a float or double in your extended types.


ImaginaryHuman(Posted 2009) [#7]
Thanks for the feedback guys!

It looks like I'll have to rewrite some code, then, to either add FloatShape and DoubleShape references as new fields in Shape, or just in-line it to one bloated Shape object containing some potentially unused fields.

I appreciate what Nilium is saying about proper use of OO design principles, ie I should really have Get and Set methods to access the fields rather than directly accessing them. And that probably would be strictly `correct` in terms of OOp'ness. But to me these methods are inefficient. I know it could potentially make later changes easier, not having to re-write lots of references to changed fields, but since I don't think it likely that these fields will change I don't see a need for me to use it. I take some issue with trying to make it easier for me to write and modify the code, because it has the side effect of making the compiled program slower to execute.

Also I prefer to directly access fields from anywhere in my code, directly. Yes it's a bit old-school procedural-design etc but that's my choice for now.


Jesse(Posted 2009) [#8]
the biggest problem there is that you just can't swap variables. you have to create instances of each. if the instance you created(such in the base)don't contain the variable then you wont be able to use it. I don't know exactly what your goal is but you can try something like this:

Type TPoly
	Field Format:Int=0
	Field shape:Tshape
	Method Load(s:Tshape)
		shape = s
	End Method
	Method clear()
		shape.clear()
	End Method
End Type
Type Tshape Abstract
	Method clear() Abstract
End Type

Type ShapeFloat Extends TShape
	Field Vertices:Float Ptr
	Method clear()
		vertices = Null
	End Method		
End Type

Type ShapeDouble Extends TShape
	Field Vertices:Double Ptr
	Method clear()
		vertices =Null
	End Method
End Type

Local ShapeToUse:Tpoly=New Tpoly
ShapeToUse.Format=0
If ShapeToUse.Format=0 Then ShapeToUse.Load(New ShapeFloat) Else ShapeToUse.Load(New ShapeDouble)
shapeToUse.clear()

[edited]
and this is not slower than having to add a couple of "If" statements.
which you would have to use if you do it your way.


ImaginaryHuman(Posted 2009) [#9]
Thanks for the effort Jesse. I am probably going to just add:

Field ShapeF:FloatShape
Field ShapeD:DoubleShape

to my Shape object. Each of them contain several fields of either float or double format and this looks like it'll be fairly sensible.


Brucey(Posted 2009) [#10]
I am probably going to just add ... to my Shape object

Right. Better to stuff everything into one Type than build a design using polymorphism :-)


Jesse(Posted 2009) [#11]
?
Are you being sarcastic?


Brucey(Posted 2009) [#12]
I hope so :-p


plash(Posted 2009) [#13]
Are you being sarcastic?
It seems that he is. I find it surprising that people haven't caught a hold on Brucey's character yet.


Brucey(Posted 2009) [#14]
I find it surprising that people haven't caught a hold on Brucey's character yet

Probably because he's pretty much character-less...

... although I think I'm still missing something, as I often get a lairy eye going through customs. Pah!


Jesse(Posted 2009) [#15]
I think you are correct. As opposed to being arrogant. Oh Well.