Is type not extended...

BlitzMax Forums/BlitzMax Programming/Is type not extended...

fredborg(Posted 2007) [#1]
Hi,

Is there a direct way to checking if a type instance is an unextended type, instead of testing against every extended type?
Type Bob; End Type
Type Jim Extends Bob; End Type
Type Joe Extends Bob; End Type
Type Jan Extends Bob; End Type
Type Jon Extends Bob; End Type

Local a:bob = New bob
Print "unextended bob? "+IsThisJustABob(a) 

' Test against other classes, potentially
' hundreds of types would need testing, and
' some of them may be "unknown" to this part of the code
Function IsThisJustABob(i:Bob)
	If i=Null Return False
	If Jim(i) Return False
	If Joe(i) Return False
	If Jan(i) Return False
	If Jon(i) Return False
	Return True
EndFunction

' Hypothetical singular test
Function IsThisJustABob2(i:Bob)
	If Unextended(Bob(i)) Return True
EndFunction
I would like to avoid having to test against lots of other, potentially unknown, types, and instead simply test once.

I realise I could tag a type with a custom id, but for reasons of portability etc. I would like to avoid this.


Dreamora(Posted 2007) [#2]
Sadly: No there is no way to check for unextended as there is defacto nothing unextended. Everything extends from Object.

It would not be really efficient to try doing so anyway.

But with the stuff Mark mentioned in his worklog (reflection) you should be able to do such a check much faster as you can ask the class what it is and what is was extended from.
Right now, this has to be done manually


BlackSp1der(Posted 2007) [#3]
use a method or field with extended value true or false

Type Bob
	Method extended(); EndMethod
End Type
Type Jim Extends Bob
	Method extended(); Return True;EndMethod
End Type
Type Joe Extends Bob
	Method extended(); Return True;EndMethod
End Type
Type Jan Extends Bob
	Method extended(); Return True;EndMethod
End Type
Type Jon Extends Bob
	Method extended(); Return True;EndMethod
End Type

Local a:bob = New bob
Print "unextended bob? "+IsThisJustABob(a) 

' Test against other classes, potentially
' hundreds of types would need testing, and
' some of them may be "unknown" to this part of the code
Function IsThisJustABob(i:Bob)
	If i=Null Return False
	Return Not i.extended()
EndFunction



Dreamora(Posted 2007) [#4]
extended:int() you mean and return false; on bobs method, right?


JoshK(Posted 2007) [#5]
CLASS_FOO=1
CLASS_MOO=2

Type foo

field class:Int

Method New()
class=CLASS_FOO
EndMethod

EndType


Type moo extends foo

field class:Int

Method New()
class=CLASS_MOO
EndMethod

EndType


For foo=eachin something:TList
Select foo.class
Case CLASS_FOO

Case CLASS_MOO

EndSelect


fredborg(Posted 2007) [#6]
Yes, thanks :) This is how I do it right now, but I would rather do it without setting a class or extended value/method. Maybe I'm just lazy...


Dirk Krause(Posted 2007) [#7]
So this is the obvious solution:

class Bob:
  pass
  
class Jim(Bob):
  pass

def IsThisJustABob(o):
  return o.__class__.__name__ == "Bob"

a = Bob()
b = Jim()

print IsThisJustABob(a)
print IsThisJustABob(b)


oops ... this is Python.

PS: sorry, simply couldn't resist. Sorry for any inconvenience.


H&K(Posted 2007) [#8]
Override ToString()
Then you have a full string to give you all the info you want.
You could for example make each type have a line, then call its supper and add another line etc.
So if the first word is "BaseClass" then you know its not extended


UByte(Posted 2007) [#9]
I'm not proud of this, and am not certain if it works on all platforms or will with future updates but interesting non-the-less...

'Returns a pointer to a class for a given object 'obj'
Function GetClassForObject:Byte Ptr(obj:Object)
	Local objPtr:Int Ptr = Int Ptr((Byte Ptr(obj)) - 8)
	Return Byte Ptr(objPtr[0])
End Function

'Returns a pointer to the super-class of a class pointed to by a given pointer 'class'
Function GetSuperClass:Byte Ptr(class:Byte Ptr)
	Return Byte Ptr((Int Ptr(class))[0])
End Function

'Returns the name of a class pointed to by a given pointer 'class'
Function GetClassName:String(class:Byte Ptr)
	If Not class Then Return Null
	Local debug_scope:Int Ptr = Int Ptr((Int Ptr(class))[2])
	Local szClass:Byte Ptr = Byte Ptr(debug_scope[1])
	Return String.FromCString(szClass)
End Function

'Returns the name of the class for a given object 'obj'
Function GetClassNameForObject:String(obj:Object)
	Return GetClassName(GetClassForObject(obj))	
End Function

'Returns TRUE for an object 'obj' that has a super class named 'className', otherwise returns FALSE
Function IsInstanceOf:Int(obj:Object, className:String)
	className = className.ToLower()
	Local class:Byte Ptr = GetClassForObject(obj)
	While GetClassName(class).ToLower() <> className
		class = GetSuperClass(class)
		If Not class Return False
	Wend
	Return True
End Function


Implementing your function is as simple as...

Function IsThisJustABob:Int(i:Bob)
	Return GetClassNameForObject(i) = "Bob"
End Function



Koriolis(Posted 2007) [#10]
Neat. You'd probably get fired for using such a trick at work, but as the guards show you the way out you'd be walking with proud ;)


Who was John Galt?(Posted 2007) [#11]
Ah I'm liking it, Dafs.


fredborg(Posted 2007) [#12]
Now, that's more like it! Very cool Dafs! *It would be a neat addition to the language*