Passing Types to functions
BlitzMax Forums/BlitzMax Beginners Area/Passing Types to functions
| ||
Hello again for the second time in under 12 hours! So this has been bothering me for a while, how do you pass an actual type (not an instance of the type) to a function? For example, I want to do this: Type TBall Method New() Objects.Addlast(self) EndMethod EndType Type TDrWatson Method New() Objects.Addlast(self) EndMethod EndType Function ObjectCount:Int(Obj:Type) Local num:Int For Local o:Obj = EachIn Objects num:+1 Next Return num End Function Global Objects:TList=new TList new TBall new TBall new TDrWatson print ObjectCount(TBall) print ObjectCount(TDrWatson) However I simply get told "Compile Error: Expecting identifier but encountered Type". This leads me to think that maybe the solution lies in pointers. There are other things this would be useful for, for instance functions which can create generic objects depending on which object is passed, etc. I do kind of have a solution in mind for if this isn't possible, that is to assign each type a Const ID thing, and just check for that. However that would be a lot clumsier, and I'd prefer not to have to. |
| ||
In essence, I'm not sure you can, although there might be a way using reflection. However, I thought it might be worth mentioning a few points about your code. 1. When a new type instance is created, the New() method is run for the new type instance. Remember, a BlitzMax function doesn't have a type instance associated with it - you can call functions without a specific instance, for example... TBall.myFunction()You wouldn't be able to do that with a method. You'd have to make a new ball, and then call the method with it. Local tmpBall:TBall = New TBall tmpBall.myMethod()2. I see what you are trying to do but I'm not entirely sure it can be done that way, unless you start using reflection. Instead, you may want to add functions to each type to count how many of its own type it can find. 3. Finally, I think it's bad practice to put parentheses "()" after your end keywords. You don't need them. How about something like this: Global lstObjects:TList = New TList Type TBall Method New() 'The New() you are attempting to use, is actually a method. lstObjects.Addlast(Self) EndMethod Function CountInList( pList:TList ) Local i% For Local tmpBall:TBall = EachIn pList i:+1 Next Return i EndFunction EndType Type TDrWatson Method New() lstObjects.Addlast(Self) EndMethod Function CountInList( pList:TList ) Local i% For Local tmpDrWatson:TDrWatson = EachIn pList i:+1 Next Return i EndFunction EndType New TBall New TBall New TDrWatson Print "Total No. of Objects: "+ lstObjects.Count() Print "No. of Balls: " + TBall.CountInList( lstObjects ) Print "No. of Dr Watsons: " + TDrWatson.CountInList( lstObjects )Hope this helps! :-) |
| ||
Arrrrghhhhh, I knew new is a method, I can't believe I typed function, and same for putting ()s on the end of ends! (and I have fixed my code example accordingly) As for your example, that might be just what I was looking for. The thing is, what I'm trying to do here isn't quite as simple as what I asked, because all of my objects are extending a base object. I tried my ID method just now using Globals in the types, but it kept referring to the ID assigned to the base type. I shall proceed to test your solution in the context of my program, and edit when I see if it works. |
| ||
3. Finally, I think it's bad practice to put parentheses "()" after your end keywords. You don't need them. Parenthesis make it clear that you're referencing a function/method rather than a global/field. Things looking like what they are = good practise, surely? |
| ||
@Sledge, things break if you stick parentheses after end... (wait were you agreeing or disagreeing?) I realised that for your technique SebHoll, you need to have that function in every type, and since I'm trying to make a game framework which avoids having to do repetitive things like that, it's not an option (even though it's a cool idea). So I settled on something like this: Global Objects:TList=New TList Type TObject Field id$ Method New() Objects.addlast(Self) EndMethod ''' etc etc game framework stuff goes here EndType Type TBall Extends TObject Method New() id="Ball" EndMethod EndType Type TLulz Extends TObject Method New() id="Lulz" EndMethod EndType Function CheckInList%(name$,list:TList) Local num%=0 For Local c:TObject=EachIn list If name="" Or name=c.id num:+1 Next Return num EndFunction New TLulz New TLulz New TBall Print CheckInList("Ball",Objects) Print CheckInList("Lulz",Objects) That might solve the particular problem, but it still leaves me wondering if it _is_ possible to reference to Types like I mentioned. I mean, you can refer to functions and methods (there are function and method types), but not Types themselves. |
| ||
wait were you agreeing or disagreeing? I was agreeing with him but I didn't know it because you edited before I read his correction (so I assumed he was referring to something different)! Par for the course on teh interwebz. Might be worth comparing enumerated values rather than strings... I think string comparisons might wind up significantly slower with large numbers of instances. Also, why not separate lists for each type? And which list you total depends on the type parameter passed? (ie check against type once at the start of the process rather than against each instance) EDIT: it still leaves me wondering if it _is_ possible to reference to Types like I mentioned Actually I thought you could... ie when you've got a list containing instances of different types, 'local tempInstance:whatever = eachin myList' would skip anything not of type whatever. Is this not the case? [Looks at SebHoll's code -- yes it is! I'd select...case the temp instance that you traverse the list with, then, if you must have a single list. It'll be ugly but at least it can all be in one function rather than spread over various methods] |
| ||
Hello Spacerat, Look at docs on "User Defined Types", relevant quote: "The Extends part is optional. If omitted, the user defined type extends the built in Object type." This probably doesn't accomplish exactly what you want, but, may start you towards where you wanna go with it. I modified your code above as follows: Type TBall Method New() Objects.Addlast(Self) EndMethod EndType Type TDrWatson Method New() Objects.Addlast(Self) EndMethod EndType 'Here: Function ObjectCount:Int() Local num:Int For Local o:Object = EachIn Objects num:+1 Next Return num End Function 'end modified code. Global Objects:TList=New TList New TBall New TBall New TDrWatson Print ObjectCount() Print ObjectCount() ======= Runs and returns 3 and 3 again. Hope it helps. |