polymorphing

BlitzMax Forums/BlitzMax Beginners Area/polymorphing

This is an extract of a program I am working on:
Type a
	Field z%
End Type
Type b Extends a
	Field z% = 2
End Type
Type c Extends a
	Field z% = 3
End Type
Local me:a = New c
Print me.z


I am trying to display the field z% with the value of 3 but I get 0. I am assuming it accessing the field z in the a type. can anybody tell me what I am doing wrong. Or is this a compiler bug?

Your error is:

Field z is defined in a, you can't redefine it.

So what you need to do is using the default constructor to set the value z

Type a
	Field z%
End Type
Type b Extends a
	Method New()
		z = 2
	End Method
End Type
Type c Extends a
	Method New()
		z = 3
	End Method
End Type
Local me:a = New c
Print me.z


so why isn't it giving me any erros. and why can't I access them like I access methods. I can clearly define the same method on the parent and on the child and I am able to access them respectively. I thought that polymorphing was also for fields not only for methods.
I had thought about your answer myself but I wanted to make shure. Is that normal for all languages or Just for Bmax?
I started learning OOP here with bmax about a year ago so don't really comprehend the syntax too well.

surely you want to have me as type C since it's a C you're creating?

Methods allow overriding as it makes sense there as the implementation can change.

A field is a field, its implementation can't change so no use why overriding should work.

But thats exactly why the default constructor exist, to initialize extended types correctly.



And I think this is how all OO (beside C++ perhaps which just uses 20 year old design ideas) work. A property that is defined by a extended class can't be "overdefined" again unless the language support undefine / redefine (Eiffel for example).

BM does not support redefinition or any selection / redefine / undefine. It only supports overloading of an implementation (you can't redefine the declaration sheme of a function / method as well, the types must be the same for any overriden version)

If you are going to use fields of the same name, then you have to make sure that the object is cast to the right type.

In your example you have cast your type C to an A, so it trys to use the field in A. If you recast it back to a C, or make Me a C in the first place, you should get the value you expect

@ perturbatio: no, Me is supposed to be a parameter to a function that handles types b and c like this:
Type a
	Field z%
End Type
Type b Extends a
	Field z% = 2
End Type
Type c Extends a
	Field z% = 3
End Type


function handleit(it:a)
 print it.z
end function

Local me:c = New c
handleit(me)
you:b = new b
handleit(you)


In that case you're 'upcasting' 'me' and 'you' to object 'a' so it will use the 'z' from type 'a'.
I don't really know this kind of stuff but I think you have to use...
Function handleit(it:Object)
		If b(it) Print b(it).z
		If c(it) Print c(it).z
end Function

There's been a few posts on this but I can' remember the right terminology to sugges a search.
<edit> Apologies if I've missed the boat.

Thats totally morronic.
The following source works and that although this is definitely no expected behavior nor anything near usefull / desired. It totally defeats the use of inheritance if dublicated field names are seperated instead of overridden

Type a
	Field z%
End Type
Type b Extends a
	Field z% = 2
End Type
Type c Extends b
	Field z% = 3
End Type
Local me:a = New c
handleit(me)
End

Function handleit(it:a)
 Print it.z
 If b(it)	Print "B: " + b(it).z
 If c(it)	Print "C: " + c(it).z
End Function


EDIT: This would already be the second type based compiler error on 1.22 hopefully the last one (the other is calling functions from type instances which then have a self)

I guess I am going Dreamora's way is simpler and does what I want.
I am not out of the woods with this topic but I think I understand it better.

this is the silly code I was working on. not yet fixed or complete. it is a math drill program for my second grade daughter to better her skills. just use your own font :
'math program
SuperStrict 

Type tmath
	Field x%,y%
	Field operand%
	Field operator%
	Field answer%
	Field text$
	Field txt$
	Field width%
	Field sign$
	Field correct%
	Field wrong%
	Field index% 
	Field density%[] = [10,20,30,40,50]
	Global level% = 0
	Global completed%[4]
	Method create() Abstract
	
	Method Inputs:String(x1% = -1,y1% = -1)
		If x1 = -1 Then x1 = x
		If y1 = -1 Then y1 = y 
		Local c:String = Chr(GetChar())
		If txt.length < width Then If c=>"0" And c <="9" Then txt=txt+c
		If KeyHit(KEY_BACKSPACE) And SizeOf(txt)>1 Then  txt = Left$(txt,txt.length-1) 
		SetColor 0,255,0
		DrawText txt,x,y
		If KeyHit(KEY_ENTER) Local name:String = txt; txt = Null ;Return name
	End Method
	Method generate()
		
		operand = Rand(0,9)
		operator = Rand (0,9)
		If operand < operator
			Local temp% = operand
			operand = operator
			operator = temp
		EndIf
	End Method	

	Method display()
		Local d$ = RSet(String(operand),4)
		Local r$ = sign+RSet(String(operator),3)
		Local tx1% = (GraphicsWidth()-TextWidth(text))
		Local rx1% = (GraphicsWidth()-TextWidth(r$))
		Local dx1% = (GraphicsWidth()-TextWidth(d$))
		Local sx%  = (GraphicsWidth()-TextWidth("____"))
		Local h%   = TextHeight("X")
		Local w%   = TextWidth("____")
		Local th%  = (GraphicsHeight()-h)
		SetColor 200,50,0
		DrawText text,tx1/2,th/8
		SetColor 50,200,0
		DrawText d$,dx1/2,th/4
		SetColor 0,50,200
		DrawText r$,rx1/2,th/4+h
		SetColor 200,50,50
		DrawText "____",sx/2,th/4 + h+10
		DrawRect  sx/2,th/4 + h*3,w,h
		x = sx/2+w - TextWidth(String(answer))
		y = th/4+h*3
	End Method
	
End Type

Type Taddition Extends Tmath	 
	Method create()
		text = "ADDITION"
		sign = "+"
		generate()
		answer = operand + operator
		width = String(answer).length
	End Method
	
End Type

Type Tsubtraction Extends Tmath
	Method create()
		text$ = "SUBTRACTION"
		sign$ = "-"
		generate()
		answer = operand - operator
		width = String(answer).length	
	End Method

End Type

Type Tmultiplication Extends Tmath
	Method create()
		text$ = "MULTIPLICATION"
		sign$ = "X"
		generate()
		answer = operand * operator
		width = String(answer).length
	End Method
	

End Type

Type Tdivision Extends Tmath
	Method create()
		text$ = "DIVISION"
		sign$ = "/"
		Repeat	
			generate()
		Until operator > 0
		answer = operand * operator
		Local temp% = answer
		answer = operand
		operand = temp
		width = String(answer).length
	End Method
	
	Method display()
		Local d$ = String(operand)
		Local r$ = String(operator)
		Local tx1% = (GraphicsWidth()-TextWidth(text))
		Local rx1% = (GraphicsWidth()-TextWidth(r$))
		Local dx1% = (GraphicsWidth()-TextWidth(d$))
		Local sx%  = (GraphicsWidth()-TextWidth("____"))
		Local h%   = TextHeight("X")
		Local w%   = TextWidth("____")
		Local th%  = (GraphicsHeight()-h)
		SetColor 200,50,0
		DrawText text,tx1/2,th/8
		SetColor 50,200,0
		DrawText "____",rx1/2,th/4+h
		SetColor 0,50,200
		DrawText r$,rx1/2-TextWidth("X"),th/4+h*2-12
		SetColor 50,200,0
		DrawText "|",rx1/2-12,th/4+h*2-12
		SetColor 200,50,50
		DrawText d$,rx1/2-12+TextWidth("|"),th/4+h*2-12
		DrawRect rx1/2,th/4+h-12,w,h
		x = rx1/2+12
		y = th/4+h
		
	End Method
End Type

Function lesson%(Math:tmath Var,z% Var )
	
	If z Then 
		Math.create()
		z=0
	Else
		DrawText " Correct = "+math.correct,0,0
		DrawText "   Wrong = "+math.wrong,400,0
		If tsubtraction(math) Then DrawText "index = "+tsubtraction(math).index,0,200
		
		Math.display()
		Local c$ = math.inputs()
		If c$ 
			Local check% =Int(c$)
	    	If check = Math.answer
				z = 1
				math.correct:+1
			Else
				math.wrong :+ 1 
			EndIf
			If math.density[math.level]<math.correct Then 
				math.completed[math.index] = True
				math = Null
				FlushKeys
			EndIf  
		EndIf
	EndIf

End Function	
Function menu:tmath(z% Var)
	DrawText "   MENU",200,100
	DrawText " 1 addition",200,200
	DrawText " 2 subtraction",200,200+TextHeight("X")
	DrawText " 3 division ",200,200+TextHeight("X")*2
	DrawText " 4 multiplication",200,200+TextHeight("X")*3
	Local M:tmath

	Select 1
		Case KeyHit(KEY_1)
			z = 1
			FlushKeys()
			M= New taddition			
			If m.completed[0] Then Return Null
			Return M
		Case KeyHit(KEY_2)
			z = 1
			FlushKeys ()
			M = New Tsubtraction
			If m.completed[1] Then Return Null
			Return M
		Case KeyHit(KEY_3)
			z = 1
			FlushKeys()
			M = New Tdivision
			If m.completed[2] Then Return Null
			Return M
		Case KeyHit(KEY_4)
			z = 1
			FlushKeys()
			M = New Tmultiplication
			If M.completed[3] Then Return Null
			Return M
		End Select
			
End Function



Graphics 800,600,16 '640,480,16
Local font:timagefont = LoadImageFont("TT1001M_.TTF",48,SMOOTHFONT)
SetImageFont(font)
Local math:Tmath 

SeedRnd MilliSecs()

'addition.create()
'subtraction.create()
'multiplication.create()
Local z%

Repeat
	If math 
		lesson%(math,z) 
	Else 
		math=menu(z)
		If math
			math.correct= 0
			math.wrong = 0
			math.level= 0
		EndIf
	EndIf
	Flip()
	Cls()
Until KeyDown(KEY_ESCAPE)


lol, guys, your Polymorph doesnt work cuz ur sorceress doesnt have enough mana to cast it, lol.

WORD!