New Self
BlitzMax Forums/Brucey's Modules/New Self
| ||
BlitzMax NG doesn't seem to like this pattern, which is supported in BlitzMax BRL:Type MyException Function Make:MyException(code:Int, extra:Object = Null) Local e:MyException = New Self ' <--- Syntax error: expecting identifier e._code = code ; e._extra = extra Return e End Function Function Raise(code:Int, extra:Object = Null) Throw Self.Make(code, extra) ' <--- Illegal use of Self within static scope End Function End Type It's not an accidental feature; BlitzMax BRL supports Self for types in the logically-expected contexts and gives clear error messages (referring to the fact that they're not Objects) if you misuse them, so it was definitely designed this way. Can this be implemented? (For that matter, is reaching 1:1 with BlitzMax BRL on minor issues like this considered a goal, or a nuisance?) I notice that the second message also indicates that NG has consciously made a decision on this matter, but it's a different one from BRL. Correcting a perceived bug, or simply an independent design choice? I use this a lot; it seems like better style than explicit repetition. Good if it's long, too. |
| ||
| Can this be implemented? Sure :-) Would you like to open an issue? ( https://github.com/bmx-ng/bcc/issues ) |
| ||
| Thanks! Opened. |
| ||
| Aside the bug: nice idea, really saves typing long typenames. A pity this does not work for return types (method get:self()) - would save some writing when else having to override methods just to return the extended type instead of the original one. Current
Type TBaseClass
Field x:int
End Type
Type TExtendedClass extends TBaseClass
Field extendedProperty:int
End Type
Type TBaseClassCollection
global instance:TBaseClassCollection
Function GetInstance:TClassCollection()
return instance
End Function
Method GetChild:TBaseClass(guid:string); ...;Return child; End Method
End Type
Type TClassCollection extends TBaseClassCollection
Function GetInstance:TClassCollection()
'handle potentially needed collection conversion from base collection
...
return TClassCollection(instance)
End Function
Method GetChild:TExtendedClass(guid:string); ...;Return TExtendedClass(Super.GetChild(guid); End Method
End Type
I use similar constructs for various collections (as vanilla does not allow interfaces - and I need to avoid cyclic dependencies - which enforces me to have base classes to refer to, and implementations/extended classes to specialice behaviour). Without overriding "GetChild" you will have to "cast-verify-type" on your own, also this allows chaining:
TBaseClassCollection.GetInstance().GetChild("bla").x
TClassCollection.GetInstance().GetChild("bla").extendedProperty
@Yasha Is there some simple way to simplify above's approach? Something similar to the "new self" 'secret' I do not know? bye Ron |
| ||
| Not one I can think of, sorry. To be honest I tend to do the opposite, work a lot with Object and Invoke. My own de-facto solution regarding interfaces in the BRL compiler (not currently using my own Interface patch in production, perhaps I should) is to do something like: Type IFooBar Final
Function Foo(_self:Object)
Local _foo:TMethod = TTypeId.ForObject(_self).FindMethod("Foo")
If _foo Then _foo.Invoke(_self, Null)
End Function
Function Bar:Int(_self:Object, x:Int)
Local _bar:TMethod = TTypeId.ForObject(_self).FindMethod("Bar")
If _bar Then Return Int(String(_bar.Invoke(_self, [Object(String(_self))])))
End Function
End Type
Function Implements:Int(o:Object, i:String)
Local t:TTypeId = TTypeId.ForName(i)
If t.ExtendsType(ct) Then Return True
While t <> ObjectTypeId
If t.Metadata(i) Then Return True
t = t.SuperType()
Wend
Return False
End Function
Type A { IFooBar }
Method Foo()
Print "A foo"
End Method
Method Bar:Int(x:Int)
Print "A bar received " + x
End Method
End Type
IFooBar.Foo(New A)...etc. It's not very formally codified actually. Lucky thing performance isn't an issue for my code. |
| ||
| While this is surely not the worst approach, I think there must exist something "easier" (the invokation is a bit ... hmm... hard to read). Using Reflection might be a bit "heavy" (albeit I do not know the impact but loosely remember, that there was some talk about it, when Mark introduced it to BlitzMax). Once NG is doing all I need (read: works and the modules compile fine :-) it might be a good chance to cut loose ends and to switch things to use "interfaces" (which Brucey nicely implemented in NG already)... Feel free to come up with other ideas :-) bye Ron |
| ||
| Thanks for changing this. (Took me an embarrassingly long time to work out that the fix was applied to a different branch.) Now more of my project compiles, I have more incompatibilities to report... which I'm sure is delightful news. I'll do that over at the issues list. |