{"id":2574,"date":"2017-02-18T11:37:34","date_gmt":"2017-02-17T23:37:34","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=2574"},"modified":"2017-02-18T11:37:34","modified_gmt":"2017-02-17T23:37:34","slug":"anonymous-classes-identity-exposed","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/2574\/","title":{"rendered":"Anonymous Classes: Identity Exposed!"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">2<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p>In <a href=\"https:\/\/www.deltics.co.nz\/blog\/posts\/2523?preview_id=2523\">my previous post on Anonymous Classes<\/a> I erroneously referred to them as &#8220;dynamic objects&#8221; (thanks to commentors for pulling me up on that).<\/p>\n<p>Dynamic objects are something else entirely (although what <em>precisely<\/em> they might mean can vary on different platforms and in different languages).  I have now corrected that post on this point, and also on <a href=\"https:\/\/twitter.com\/dwarfland\/status\/831463486010056705?cn=cmVwbHk%3D\">another point that Marc Hoffman called me out on<\/a> (again, thanks for that).<\/p>\n<p>And so the time has now come to expose the <strong>true<\/strong> identity of these so called &#8220;Anonymous Classes&#8221;.<\/p>\n<p><!--more--><\/p>\n<p>This won&#8217;t be a very long post since the identity of an anonymous class is not especially well hidden.  It&#8217;s just that knowing that identity is not very useful (to us as application developers &#8211; it is of course crucial to the compiler).<\/p>\n<p>So all that is required is a very simple example:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\nnamespace anonClassName;\r\n\r\n  type\r\n    Program = class\r\n    public\r\n      class method Main(args: array of String): Int32;\r\n      begin\r\n        var anon := new class( foo := 'The question ?', bar := 42);\r\n        var obj  := new Object;\r\n\r\n        writeLn(typeOf(anon));\r\n        writeLn(typeOf(obj));\r\n\r\n        readLn;\r\n      end;\r\n    end;\r\n\r\nend.\r\n<\/pre>\n<p>Using the (optional) <a href=\"https:\/\/www.deltics.co.nz\/blog\/posts\/2470\">inline implementation syntax now supported in Oxygene<\/a>, this implements a simple console application which instantiate an anonymous class with 2 (two) members, good ol&#8217; <strong>foo<\/strong> and <strong>bar<\/strong>.  For comparison, a simple <strong>object<\/strong> is also instantiated for comparison.<\/p>\n<p>I then use the <strong>typeOf()<\/strong> Oxygene intrinsic to report the name of the type (i.e. class) of each of these objects.<\/p>\n<p>The output is equally simple:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n&lt;&gt;f__AnonymousType0`2[System.String,System.Int32]\r\nSystem.Object\r\n<\/pre>\n<p>And as we can see, the &#8220;so called&#8221; anonymous class isn&#8217;t actually anonymous at all.  With a slightly extended example we gain a little more insight:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n        var anonA := new class( foo := 'The question ?', bar := 42);\r\n        var anonB := new class( foo := 'Another question ?', bar := 147);\r\n        var anonC := new class( foo := 10, bar := 2 );\r\n\r\n        writeLn(typeOf(anonA));\r\n        writeLn(typeOf(anonB));\r\n        writeLn(typeOf(anonC));\r\n<\/pre>\n<p>Running this yields:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n&lt;&gt;f__AnonymousType0`2[System.String,System.Int32]\r\n&lt;&gt;f__AnonymousType0`2[System.String,System.Int32]\r\n&lt;&gt;f__AnonymousType1`2[System.Int32,System.Int32]\r\n<\/pre>\n<p>Here we can see that <strong>anonA<\/strong> and <strong>anonB<\/strong> are actually of the same type.  I don&#8217;t know precisely how the compiler works and whether context is a component in the algorithm for deriving a class name, but at the very least we can see that in this case the fact that the two classes have the same members mean that even though both are instantiated anonymously and separately, they are of the same type.<\/p>\n<p>This (in part) is what presumably enables the use of strongly typed collections of even anonymous class instances in LINQ, for example.<\/p>\n<p>Equally we can see that even though <strong>anonC<\/strong> has the same member names as <strong>anonA<\/strong> and <strong>anonB<\/strong>, it is a distinct type, courtesy of the <em>types<\/em> of those members.<\/p>\n<p>As noted, those type names are not very friendly, would not even be legal (or certainly not straightforward) to use in any code and in theory I think could change from one build to the next.<\/p>\n<p>But now the secret of anonymous classes is revealed.  They aren&#8217;t anonymous so much as just very discreet <em>and<\/em> discrete.  \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">2<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span> In my previous post on Anonymous Classes I erroneously referred to them as &#8220;dynamic objects&#8221; (thanks to commentors for pulling me up on that). Dynamic objects are something else entirely (although what precisely they might mean can vary on different platforms and in different languages). I have now corrected that post on this point, and [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":[]},"categories":[4,180],"tags":[311,13,181],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-Fw","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":2523,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2523\/","url_meta":{"origin":2574,"position":0},"title":"Anonymous Classes: Anonymous POCO&#8217;s","date":"14 Feb 2017","format":false,"excerpt":"There is another use case for anonymous classes, even simpler than that of providing implementations of interfaces: Anonymous POCO's. We're all familiar with the idea of declaring a class that identifies the members that all instances (objects) of that class have, and then creating instances of that class. Anonymous classes,\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/code-completion-java.jpg?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":2511,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2511\/","url_meta":{"origin":2574,"position":1},"title":"Anonymous Classes: Implementing Interfaces","date":"11 Feb 2017","format":false,"excerpt":"A few years ago (2011 to be precise) someone asked a question on StackOverflow about support for anonymous classes in Delphi. The reason for the question was that the poster was trying to use Delphi to develop for Android and on that platform the widespread use of callback interfaces makes\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1624,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1624\/","url_meta":{"origin":2574,"position":2},"title":"Exploring Listeners With Oxygene","date":"16 Sep 2013","format":false,"excerpt":"Part 2 in a short series demonstrating the development of a simple camera app for Android using Oxygene. In the previous instalment we looked at the basic framework of our app. For this instalment I was going to show how to implement the camera preview or viewfinder for this instalment,\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2252,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2252\/","url_meta":{"origin":2574,"position":3},"title":"Making a Noise About on a Thread","date":"13 Aug 2014","format":false,"excerpt":"I'm working on an Android app at the moment, and for a bit of fun I decided to add a startup sound to brighten the day of every user that launches it. Which gives me another opportunity to present some of the advanced language features in Oxygene that make threading\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Audio-Resource.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":3024,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/3024\/","url_meta":{"origin":2574,"position":4},"title":"Scope Elevation: Creating A &#8216;Pseudo-Namespace&#8217;","date":"31 Oct 2019","format":false,"excerpt":"In my previous post I talked about how \"namespaces\" in Delphi really don't exist for any practical purposes normally associated with the concept. Having become familiar with the concept in other languages I found I was missing them, so I devised a way to obtain some of the benefits, despite\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/niklaus-wirth-edit.jpg?fit=934%2C362&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1882,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1882\/","url_meta":{"origin":2574,"position":5},"title":"Not Your Grand-Daddy&#8217;s Pascal (or Java)","date":"15 Oct 2013","format":false,"excerpt":"I've mentioned some of the cool stuff in the Oxygene language in various posts and thought it would be a good idea to list them again, along with some others that I've not previously mentioned. Oxygene Everywhere First some of the core language features that are available on all supported\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2574"}],"collection":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/comments?post=2574"}],"version-history":[{"count":3,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2574\/revisions"}],"predecessor-version":[{"id":2577,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2574\/revisions\/2577"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=2574"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=2574"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=2574"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}