Closed GWRon closed 8 years ago
If you are interfacing with modules defined as Strict, your extending types will also need to be Strict, and not SuperStrict. Strict assumes undefined return types as Int.
Maybe modules should get SuperStrict as much as possible - as this sounds as "superstrict + strict" is possible, while "strict + superstrict" isnt.
Thanks anyways
Shouldnt this be possible:
Base: Strict Extended: SuperStrict
Base: Method Stop()
Extended Method Stop:int()
Why? Because you said in "strict" void returns default to ":int". If you blindly assume that for void returns, then the superstrict "Stop:int()" should be perfectly well defined in that case.
When doing this that way, we should get rid of many "overrridden method does not match" codes regarding old code flying around.
Are there disadvantages of this approach?
What do you think about adding some kind of "strictmode"-property to function declaration?
All original classes get the property "strict:int = 0 | 1 | 2" based on the strictmode of their source file. If they extend a class, they do set the strict-property to the value of their parent (or just return the value of the original one).
If the base file is "non"-strict, all declared classes there (if initial, not extending) get the property "strict:int = 0". Now, if you extend the classes in another file (this time strict), the validity checks use the property given in the initial class.
This gets rid of things like "Strict baseclass: Func()" and "SuperStrict extendedClass: Func:Int()".
I don't think it is a good idea to "downgrade" a superstrict method to match the return type of its strict overridden parent.
However, I am not against "updgrading" a strict method to match the void return type of its superstrict overridden parent...
Isn't this the normal expected behaviour? I mean: parent is superstrict and expects ":void". As I am not sure if I got you correct: If a superstrict parent defines ":void" and a child defines ":int" you "upgrade" that child-definition to be ":void" ? How do you handle "return True" and "return False" then (which should be able for valid "nothing = :int"-constructions).
Why on earth would you override a SuperStrict Void method with a Strict method and expect to be able to return an Int from it?
The superstrict base module/source might not care for the result of a specific function and therefore do not return anything (aka "void").
Now I extend from this type and now I am interested in the result of the overridden function - so I rely on "nothing" becomes ":int"
and do a return "myInterestedValue".
In short: a former "fire and forget" function call becomes (in the extended variant) something which enables checks for specific result values.
I know that this could get overcome with "GetLastResultID()" or similar approaches. Also do not get me wrong - I personally would adjust the base type to return ":int" in that case but I just thought about potential usage forms. If possible I would also see everything being "superstrict" by default - but as this needs a big overhaul on many modules, this is not an option.
Again: I think I did not understand your
However, I am not against "updgrading" a strict method to match the void return type of its superstrict overridden parent...
So did you mean:
base: function bla()
extended: function bla:int()
(or function bla()
but in a not-superstrict-context aka "implicit-:int")
And the extended function now becomes bla()
automatically? If so, how do you then inform about "return True" not being possible in the extended bla:int()
-function. For the average-joe-user this isn't self-explanatory then (he is reading ":int" - or assumes so because of "strict" - but is not alllowed to return an int...)
If you meant something different, please explain it to me in other words.
Do you expect this to work?
SuperStrict
Framework brl.standardio
Type TBase
Method getNothing()
End Method
End Type
Type TImpl Extends TBase
Method getNothing:Int()
End Method
End Type
in "vanilla" I would expect this to work, yes.
SuperStrict
Framework brl.standardio
Type TBase
Method getNothing()
End Method
End Type
Type TImpl Extends TBase
Method getNothing:Int()
return True
End Method
End Type
global t:TImpl = new TImpl
if t.getNothing() then print "returned True"
output
returned True
As NG now supports void
this becomes problematic. How would one use the ":void" return for something useful? Is there a reason to have ":void" when running a function-result-comparison ?
I mean: ":void" can only be void - nothing else? So would it matter if a comparison of if not func() then ...
assumes an integer of value 0 then? If it does not matter, then we could already do as if there was an :int instead of ":void".
Right, because TBase getNothing() is really getNothing:Int() - since SuperStrict isn't really super-strict.
But now we are, so the rules are tightened up. If you were coding in Java, for example, the above example would not compile either, because the return type of the overridden method should match.
I understood this part already: in a perfect scenario the extended function return type should be the same (or extending from the previous return type).
BUT ... I tried to suggest something which enables some "automagic" for strict source files extending superstrict-classes.
So:
superstrict.bmx
Superstrict
Type TSuperStrict
Method a()
return
End Method
End Type
strict.bmx
Strict
Import "superstrict.bmx"
Type TStrict extends TSuperStrict
Method a:int()
return True
End Method
End Type
local mySuperstrict:TSuperStrict = new TSuperStrict
local myStrict:TStrict = new TStrict
For the compiler "TSuperstrict.a" could be still a "void" thing... but once the user does a comparison (if mySuperstrict.a() then print "I run that method successfully"
) the compiler should allow that. So implicitely it converts that void to "0" then. So why should one call if mySuperStrict.a() then
? Because sometimes you do not know the exact type of an instance (there might be multiple types extending from TSuperStrict
but you only store them in an array TSuperStrict[]
).
It is more than just "hacky" because for other types the user expectations differ: :string
in base class versus :int
in extended class. The only difference here is, that vanilla does indeed ignore "void" and implicitely assumes "int = 0" then.
I wont worry keeping it the way it is for now: void <> int, no further discussion ;-) It is just questionable whether NG wants to try to stay compatible to vanilla in this special area.
Your logic makes no sense to me :-)
Seems we both have something in common then :-)
Dunno how to explain it understandable:
To allow this:
SuperStrict
Framework brl.standardio
Type TBase
Method getNothing()
End Method
End Type
Type TImpl Extends TBase
Method getNothing:Int()
return True
End Method
End Type
global b:TBase = new TBase
global i:TImpl = new TImpl
print "b.getNothing() = " + b.getNothing()
print "i.getNothing() = " + i.getNothing()
outputting
b.getNothing() = 0
i.getNothing() = 1
NG needs to implicitely convert "void" to "0".
Question: Why does NG not allow overriding "void" with "int", isn't "int" some kind of child of "void" (which allows more than "0" as value)? Overriding Method get:TBaseClass()
with Method get:TExtendedFromBaseClass()
is possible too?
Is it forbidden because of some C-code-interaction (when playing with external c-code from BlitzMax) ?
Edit: of course one could mention, that "0" <> "void" ... but I just try to make it work similar to vanilla while keeping the benefits you saw when adding void...
Yes. And because Void should actually be void. Therefore, if you want a less strict programming style, use Strict. If you want to use SuperStrict, you need to live within its rules.
You are right, but I was thinking of all those "beginners" who use a superstrict module / 3rd party code within their own strict-code.
BTW: feel free to close this issue (as I agree with having "void<>int")
I just tried to compile maxmod again:
The line is the following "Stop()" method:
interestingly "TChannel" defines that method exactly the same (no explicit return value).
Changing it to "Stop:int()" in TChannel AND TMaxModChannel removes the error message (and goes on to the next :p).
So this means, bcc-ng currently seem to have problems with "void" methods in modules. Doing the same in a single file works as expected, same for normal "file imports" (import "bla.bmx").