{"id":320,"date":"2013-04-14T18:31:03","date_gmt":"2013-04-14T17:31:03","guid":{"rendered":"http:\/\/bryants.eu\/blog\/?p=320"},"modified":"2013-04-14T18:31:03","modified_gmt":"2013-04-14T17:31:03","slug":"hiding-methods","status":"publish","type":"post","link":"https:\/\/bryants.eu\/blog\/2013\/04\/hiding-methods\/","title":{"rendered":"Hiding Methods"},"content":{"rendered":"<p>This week, I was trying to rewrite the inheritance checker for generics. The inheritance checker is the compiler pass which makes sure that there aren&#8217;t any problems with overridden methods, and that only abstract classes can have abstract methods.<\/p>\n<p>The question I was faced with was: Can something inherit from the same generic interface twice, with different type arguments? For example:<\/p>\n<pre>interface Processor&lt;T&gt;\r\n{\r\n  void process(T t);\r\n}\r\nclass MultiProcessor implements Processor&lt;int&gt;, Processor&lt;string&gt;\r\n{\r\n  void process(int i) {}\r\n  void process(string s) {}\r\n}<\/pre>\n<p>This makes conceptual sense, and doesn&#8217;t have any ambiguities, so it really should be allowed. Unfortunately, there are two problems that can arise if this is allowed. The first is with the low-level implementation of method overriding, which can be changed; but the second is an ambiguity that can&#8217;t be solved without substantial changes to the language. Here&#8217;s an example that should illustrate the second problem:<\/p>\n<pre>interface List&lt;T&gt;\r\n{\r\n  void add(T t);\r\n  T get(uint index);\r\n  uint size();\r\n}\r\nclass MultiList implements List&lt;int&gt;, List&lt;string&gt;\r\n{\r\n  void add(int i) { ... }\r\n  void add(string s) { ... }\r\n  int get(uint index) { ... }\r\n  string get(uint index) { ... }\r\n  \/\/ what about size()?\r\n}<\/pre>\n<p><code>MultiList<\/code> tries to be two different lists at the same time. The <code>add()<\/code> and <code>get()<\/code> methods should work fine, because they have different signatures (in plinth, the return type is part of a method&#8217;s signature). However, the <code>size()<\/code> method has the same signature no matter which list it is from. Obviously we don&#8217;t want both lists to have the same implementation of <code>size()<\/code> &#8211; we might have 2 ints and 7 strings. In order for everything to still work when we cast from <code>MultiList<\/code> to <code>List&lt;int&gt;<\/code> or <code>List&lt;string&gt;<\/code>, we need to have two different implementations.<\/p>\n<p>But with the current system, if you override a method, it overrides all of the super-type methods with the same signature, making it impossible to have two different <code>size()<\/code> implementations. The solution is to change the language to allow methods to be hidden instead of overridden.\u00a0For the unfamiliar, here&#8217;s a quick description of the difference:<\/p>\n<ul>\n<li>Hiding is what happens to fields: when you make a new one with the same name in a subtype, the one in the supertype still exists, but you can&#8217;t access it from the subtype (if you need to access it, you can cast to the supertype first and access it there).<\/li>\n<li>Overriding is what happens to methods: when you make a new one with the same signature in a subtype, the one in the supertype gets overwritten with your new one, so that everywhere you access it you are referring to the same thing.<\/li>\n<\/ul>\n<p>What we actually need to do to solve this sort of problem is to hide a method while providing an implementation for it, i.e. override it and hide it at the same time. We could provide implementations for both <code>size()<\/code> methods to do different things, and then hide one (or both) of them, so that you get two different answers when you do:<\/p>\n<pre>(cast&lt;List&lt;int&gt;&gt; multi).size()\r\n(cast&lt;List&lt;string&gt;&gt; multi).size()<\/pre>\n<p>When you do <code>multi.size()<\/code>, you get whichever of them is not hidden, or a compiler error if both of them are hidden.<\/p>\n<p>The syntax I am considering for this is similar to\u00a0C\u266f&#8217;s\u00a0<a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa664591(v=vs.71).aspx\">&#8220;explicit implementation&#8221;<\/a>\u00a0syntax for interfaces, but more flexible:<\/p>\n<pre>class MultiList implements List&lt;int&gt;, List&lt;string&gt;\r\n{\r\n  \/\/ ... add() and get() methods ...\r\n  hiding uint List&lt;int&gt;::size() { ... } \/\/ overrides List&lt;int&gt;::size()\r\n  uint size() { ... } \/\/ overrides List&lt;string&gt;::size()\r\n}<\/pre>\n<p>This gives us implementations for each of the <code>size()<\/code> methods separately, and hides <code>List&lt;int&gt;::size()<\/code> so that only <code>List&lt;string&gt;::size()<\/code> is accessible from <code>MultiList<\/code>. If we want to call <code>List&lt;int&gt;::size()<\/code>, we must first cast the <code>MultiList<\/code> to a\u00a0<code>List&lt;int&gt;<\/code>.<\/p>\n<p>This syntax will also allow you to hide a method and provide a new method with the same signature, without overriding it. For example:<\/p>\n<pre>class Bar\r\n{\r\n  uint parse(string s) { ... }\r\n}\r\nclass Foo extends Bar\r\n{\r\n  hiding uint Bar::parse(string s);\r\n\r\n  uint parse(string s) { ... }\r\n}<\/pre>\n<p>So, in order to hide a super-type&#8217;s method, we declare it with the &#8216;<code>hiding<\/code>&#8216; modifier, and instead of just giving its name, we use <code>SuperType::name<\/code>.<\/p>\n<p>Note: I am not completely decided on the keyword &#8216;hiding&#8217;. While &#8216;hidden&#8217; might make more sense, I do not expect this feature to be used very often, so I don&#8217;t want to use a keyword which people often use as a variable name.<\/p>\n<h2>Low-Level Hiding<\/h2>\n<p>The other problem I mentioned was with the low-level implementation of overriding. Currently, each method has a &#8220;disambiguator&#8221;, which is a string representation of its signature, including its name and its parameter and return types. Methods are only overridden by the plinth runtime if their disambiguator strings are equal.<\/p>\n<p>One problem with this way of doing things is that it doesn&#8217;t cope with inheriting members from the same super-type twice. To override both <code>List&lt;int&gt;::get()<\/code> and <code>List&lt;string&gt;::get()<\/code>, you would need to provide two methods which have different disambiguators, but the super-type only has one disambiguator for <code>List&lt;T&gt;::get()<\/code>, so they cannot override it properly with the current system.<\/p>\n<p>Another problem is that it doesn&#8217;t allow a method to not override a superclass method, unless it picks a deliberately non-matching disambiguator (and doing so would be bad for binary compatibility).<\/p>\n<p>To solve these problems, the way the runtime generates VFTs will have to be dramatically changed in a way I haven&#8217;t fully thought out yet. Luckily, this part of the runtime is only run once when the program is starting up, so the minor efficiency tradeoff that this will probably necessitate is almost certainly worth it.<\/p>\n<p>&nbsp;<\/p>\n<p>For now, I&#8217;ll get back to implementing generics without support for inheriting from the same type multiple times, and support for these features will be added later on.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This week, I was trying to rewrite the inheritance checker for generics. The inheritance checker is the compiler pass which makes sure that there aren&#8217;t any problems with overridden methods, and that only abstract classes can have abstract methods. The question I was faced with was: Can something inherit from the same generic interface twice, [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"_links":{"self":[{"href":"https:\/\/bryants.eu\/blog\/wp-json\/wp\/v2\/posts\/320"}],"collection":[{"href":"https:\/\/bryants.eu\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bryants.eu\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bryants.eu\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bryants.eu\/blog\/wp-json\/wp\/v2\/comments?post=320"}],"version-history":[{"count":16,"href":"https:\/\/bryants.eu\/blog\/wp-json\/wp\/v2\/posts\/320\/revisions"}],"predecessor-version":[{"id":338,"href":"https:\/\/bryants.eu\/blog\/wp-json\/wp\/v2\/posts\/320\/revisions\/338"}],"wp:attachment":[{"href":"https:\/\/bryants.eu\/blog\/wp-json\/wp\/v2\/media?parent=320"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bryants.eu\/blog\/wp-json\/wp\/v2\/categories?post=320"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bryants.eu\/blog\/wp-json\/wp\/v2\/tags?post=320"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}