About Monkey 2 › Forums › Monkey 2 Programming Help › derived class as argument for base class and other rules for inheritance
This topic contains 14 replies, has 7 voices, and was last updated by
Mark Sibly
1 year, 2 months ago.
-
AuthorPosts
-
January 19, 2018 at 8:37 am #13020
in the following code I can give a derived class as parameter for an argument defined as the base class. The same is true for assignation. Is it expect behaviour?
If I cast a derived class from the base one I can access the derived method but not the Base one!
What may I and what shouldn’t I do. What are the rules with these inheritance things?Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263Namespace myapp#Import "<std>"Using std..Function Main()Local oa:=New A()Local ob:=New B()haha(oa)haha(ob)' hoho(oa)hoho(ob)Local oa2:ALocal ob2:Boa2=ob' ob2=oaoa.a=7Print oa.aLocal ob3:=Cast<B>(oa)ob3.doMore()Print ob3.a 'not OKEndClass AField a:IntMethod do() VirtualPrint "a"EndEndClass B Extends AField b:IntMethod do() OverridePrint "b"EndMethod doMore()Print "yo!"EndEndFunction haha (o:A)o.do()EndFunction hoho (o:B)o.do()o.doMore()EndJanuary 19, 2018 at 2:36 pm #13035Probably, it’s a lang bug. The code looks correct.
January 19, 2018 at 9:30 pm #13041Shouldn’t the downcasting on line 26 be an error?
January 19, 2018 at 10:05 pm #13043Look all right to me. Pulling out the noise, code is:
Monkey123456789101112131415Class AEndClass B Extends AEndFunction Main()Local a:=New ALocal b:=Cast<B>( a ) 'cast fails (ie: returns null) as 'a' is not of type BAssert( b )EndShouldn’t the downcasting on line 26 be an error?
Don’t think so. B is a subclass of A, so Cast<B>( a ) is semantically correct (ie: compilable) if ‘a’ is of class A (or any other superclass of B). In general, the compiler can’t know at compile time what the true class of ‘a’ is though.
January 19, 2018 at 10:49 pm #13045I too expected that to be an error since class a doesn’t know about class b but class b does know about class a…But I like that it returns a null.
January 20, 2018 at 8:04 am #13055ok thanks
I thought invoking a method on a Null instance was giving an error..
January 20, 2018 at 8:39 am #13056I thought invoking a method on a Null instance was giving an error..
It was and it should. In debug mode I get the following error…
Attempt to invoke method on null instance
…on line 29, ob3.doMore()
This is 100% correct behaviour – you can’t invoke a method on a Null instance. You could a while back but haven’t been able to for some time now.
January 20, 2018 at 10:12 am #13059Strange… Here with latest dev branch using “i686-6.2.0-posix-dwarf-rt_v5-rev1” and windows 10 I get the following. (see picture, whole code and console prints are visible, code attached as file too.)
January 20, 2018 at 8:37 pm #13116Can you post output of console? You can copy and paste from console by clicking in console, then using edit menu to select-all/copy (Yes, this should be smoother, my fault really).
[edit]Ok, can reproduce, seems to be a mingw thing. Under msvc x64 I get:
ob is Null
-now trying to invoke the doMore() method on ‘ob’ Null intance-Attempt to invoke method on null instance
ie: it should die before the ‘yo!’ Will check it out…
January 20, 2018 at 9:18 pm #13122January 21, 2018 at 11:54 am #13141This one seems to have a link to an object instance somewhere in memory, but the displayed value is Null.
Monkey123456789101112Class AEndClass B Extends AEndFunction Main()Local a := New ALocal b := Cast<B>(a)Print(Typeof(b) = Typeof<Object>)Print(b = Null)EndHowever trying overloading the To operator makes the program behave correctly.
Monkey12345678910111213Class AMethod To:B()Local b := New Bb.b = Self.aReturn aEndClass BMethod To:A()Local a := New Aa.a = Self.bReturn aEndHowever I know that the point of the post is to stress test the compiler (I am not trying to patch the code example). But other than that you would consider that as a programming practice, super-casting is always ambiguous, because most of the times you can’t be sure how the derived type translates to their parent.
As a point of reference in C# language this operation is not permitted. So perhaps Monkey would introduce the same restriction, to promote more formal and strict habits.
Monkey123456789101112131415161718class A{}class B : A{}class MainClass{public static void Main(string[] args){var a = new A();var b = (B)a; // <-- This won't happen...// System.InvalidCastException has been thrown// Unable to cast object of type 'TestSuperCasting.A' to type 'TestSuperCasting.B'.}}January 21, 2018 at 9:29 pm #13157This one seems to have a link to an object instance somewhere in memory, but the displayed value is Null.
Please post runnable examples including Main() – how am I meant to know what goes before that etc?
January 22, 2018 at 5:10 am #13160var b = (B)a; // <– This won’t happen…
> // System.InvalidCastException has been thrownI’m not too keen on making Cast throw an exception or runtime error, as cast currently doubles as an ‘intanceOf’ style operation, eg: you can go…
If Cast<B>( a ) Print "A as a B!"
Changing this behaviour would break a ton of my own code and would mean I would have to add ‘InstanceOf’ or similar to the language. I’m quite happy with current behaviour.
January 22, 2018 at 12:37 pm #13166I updated the previous post to include the code sample.
January 22, 2018 at 10:21 pm #13170Cheers, I thought that was probably it but for the sake of clarity and to minimize confusion it’s always nice to be as clear as possible.
Same answer though, Cast wont be throwing an exception any time soon. Even if it did, I’d still like something ‘castish’ which is faster than “If i instanceOf T then t:=Cast<T>( i )” which effectively needs to do 2 downcasts.
-
AuthorPosts
You must be logged in to reply to this topic.
