{"action":"created","issue":{"url":"https://api.github.com/repos/colobot/colobot/issues/807","repository_url":"https://api.github.com/repos/colobot/colobot","labels_url":"https://api.github.com/repos/colobot/colobot/issues/807/labels{/name}","comments_url":"https://api.github.com/repos/colobot/colobot/issues/807/comments","events_url":"https://api.github.com/repos/colobot/colobot/issues/807/events","html_url":"https://github.com/colobot/colobot/pull/807","id":168503059,"number":807,"title":"Add Full Support for Polymorphism","user":{"login":"CyborgMaster","id":1882579,"avatar_url":"https://avatars.githubusercontent.com/u/1882579?v=3","gravatar_id":"","url":"https://api.github.com/users/CyborgMaster","html_url":"https://github.com/CyborgMaster","followers_url":"https://api.github.com/users/CyborgMaster/followers","following_url":"https://api.github.com/users/CyborgMaster/following{/other_user}","gists_url":"https://api.github.com/users/CyborgMaster/gists{/gist_id}","starred_url":"https://api.github.com/users/CyborgMaster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CyborgMaster/subscriptions","organizations_url":"https://api.github.com/users/CyborgMaster/orgs","repos_url":"https://api.github.com/users/CyborgMaster/repos","events_url":"https://api.github.com/users/CyborgMaster/events{/privacy}","received_events_url":"https://api.github.com/users/CyborgMaster/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":13,"created_at":"2016-07-31T05:38:30Z","updated_at":"2016-08-01T01:21:25Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/colobot/colobot/pulls/807","html_url":"https://github.com/colobot/colobot/pull/807","diff_url":"https://github.com/colobot/colobot/pull/807.diff","patch_url":"https://github.com/colobot/colobot/pull/807.patch"},"body":"This should resolve #540 and #683.  \r\n\r\nInheritance and polymorphism were mostly there.  I cleaned up a couple of compile time checks that prevented things like `Base b = new Child()` from compiling (even though the engine would execute it fine).  \r\n\r\nI fixed the issue with a grandchild not being able to call a grandparent method.  Turns out `CBotClass` was only doing one level of parent checking.  Now it works with recursion to handle any depth.\r\n\r\nFix the weird assignment `Child c = new Base()`, which used to compile and actually kind of run, but would behave very strangely.  Now it throws the proper `Wrong type for assignment` error.\r\n\r\nDynamic Dispatch (virtual functions) now work correctly.  `Base b = new Child(); b.overriden_method();` now properly calls the child class method instead of the base class one.  this required calling methods based off the instance type instead of the variable type in `CBotInstrMethode`.  Which then also required improving the way the `super` pointer relates to parent pointers in `CBotVarClass` (`m_pParent` is now a pointer to the parent instance instead of the parent instance itself so `super` can clone the pointer and so garbage collection works properly).\r\n\r\nI believe I have followed all the coding conventions and didn't break anything, but I haven't figured out how to run the linter or test suite yet, so I'm not sure.  I don't have time tonight to figure them out.  Hopefully I'll be able to get them running tomorrow, but I wanted to put this up here in case anyone else wanted to look at / test / comment on my approach.  \r\n\r\nIn short, the follow code now does what you would think it does: \r\n\r\n``` cpp\r\npublic class Base {\r\n\tpublic void foo() {\r\n\t\tmessage(\"foo\");\r\n\t}\r\n\r\n\tpublic void greet(string name) {\r\n\t\tmessage(\"Hi \" + name);\r\n\t}\r\n}\r\n\r\npublic class Child extends Base {\r\n\tpublic void greet(string name) {\r\n\t\tsuper.greet(\"AWESOME \" + name);\r\n\t}\r\n}\r\n\r\npublic class Grandchild extends Child {\r\n\tpublic void greet(string name) {\r\n\t\tsuper.greet(\"lame \" + name);\r\n\t}\r\n}\r\n\r\nextern void test() {\r\n\tGrandchild c = new Grandchild();\r\n\tBase b = c;  // compiles and runs correctly \r\n\tc.greet(\"jeremy\");  // outputs \"Hi AWESOME lame jeremy\"\r\n\tc.foo();  // calls grandparent method\r\n\tb.greet(\"jeremy2\");  // outputs \"Hi AWESOME lame jeremy2\"\r\n\tb.foo();\r\n\r\n        // these polymorphic assignments compile and run correctly\r\n\tBase b2;\r\n\tGrandchild g;\r\n\tb2 = new Grandchild();\r\n\tg = b2;\r\n\r\n\tBase b3 = new Child();\r\n\tGrandchild c3 = b3;  // Fails with \"Wrong type for assignment\"\r\n\r\n\tChild c4 = new Base();  // Fails with \"Wrong type for assignment\"\r\n}\r\n```\r\n\r\nLet me know what you think. \r\n\r\nNotes to self for tomorrow: \r\n+ Explain how down casting works in CBot and how that affects compile time vs run time checks for polymorphic assignments.  \r\n+ Figure out constructor / destructor inheritance\r\n\r\nAbove notes explained in a further comment on this PR [here](https://github.com/colobot/colobot/pull/807#issuecomment-236444003)\r\n"},"comment":{"url":"https://api.github.com/repos/colobot/colobot/issues/comments/236470122","html_url":"https://github.com/colobot/colobot/pull/807#issuecomment-236470122","issue_url":"https://api.github.com/repos/colobot/colobot/issues/807","id":236470122,"user":{"login":"CyborgMaster","id":1882579,"avatar_url":"https://avatars.githubusercontent.com/u/1882579?v=3","gravatar_id":"","url":"https://api.github.com/users/CyborgMaster","html_url":"https://github.com/CyborgMaster","followers_url":"https://api.github.com/users/CyborgMaster/followers","following_url":"https://api.github.com/users/CyborgMaster/following{/other_user}","gists_url":"https://api.github.com/users/CyborgMaster/gists{/gist_id}","starred_url":"https://api.github.com/users/CyborgMaster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CyborgMaster/subscriptions","organizations_url":"https://api.github.com/users/CyborgMaster/orgs","repos_url":"https://api.github.com/users/CyborgMaster/repos","events_url":"https://api.github.com/users/CyborgMaster/events{/privacy}","received_events_url":"https://api.github.com/users/CyborgMaster/received_events","type":"User","site_admin":false},"created_at":"2016-08-01T01:21:24Z","updated_at":"2016-08-01T01:21:24Z","body":"I've now also added the ability to call super destructors.  I waffled back and forth between allowing a explicit super call and having them called automatically.  I ended up settling on explicit to match the explicit super constructor calls.  That way its consistent.  So now the following works:\r\n\r\n``` cpp\r\npublic class Base {\r\n\tvoid ~Base() {\r\n\t\tmessage(\"base deconstructor\");\r\n\t}\r\n}\r\n\r\npublic class Child extends Base {\t\r\n\tvoid ~Child() {\r\n\t\tmessage(\"child desconstructor\");\r\n\t\tsuper.~Base();\r\n\t}\r\n}\r\n```"}}
{"actor":{"display_login":"CyborgMaster"}}