<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Jon Skeet: Coding Blog : Wacky Ideas, Noda Time</title><link>http://msmvps.com/blogs/jon_skeet/archive/tags/Wacky+Ideas/Noda+Time/default.aspx</link><description>Tags: Wacky Ideas, Noda Time</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>The curious case of the publicity-seeking interface and the shy abstract class</title><link>http://msmvps.com/blogs/jon_skeet/archive/2010/10/03/the-curious-case-of-the-publicity-seeking-interface-and-the-shy-abstract-class.aspx</link><pubDate>Sun, 03 Oct 2010 19:05:58 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1779234</guid><dc:creator>skeet</dc:creator><slash:comments>26</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1779234</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1779234</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2010/10/03/the-curious-case-of-the-publicity-seeking-interface-and-the-shy-abstract-class.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://noda-time.googlecode.com"&gt;Noda Time&lt;/a&gt; has a guilty secret, and I&amp;#39;m not just talking about the fact that there&amp;#39;s been very little progress on it recently. (It&amp;#39;s not dead as a project - I have high hopes, when I can put some quality time into it.) This secret is called &lt;code&gt;LocalInstant&lt;/code&gt;, and it&amp;#39;s a pain in the neck.&lt;/p&gt;  &lt;p&gt;One of the nice things about giving talks about an API you&amp;#39;re currently writing is that you can see which concepts make sense to people, and which don&amp;#39;t - as well as seeing which concepts you&amp;#39;re able to explain and which you can&amp;#39;t. &lt;code&gt;LocalInstant&lt;/code&gt; has been an awkward type to explain right from day 1, and I don&amp;#39;t think it&amp;#39;s improved much since then. For the purpose of this blog post, you don&amp;#39;t actually need to know what it means, but if you&amp;#39;re really interested, imagine that it&amp;#39;s like a time-zone-less date and time (such as &amp;quot;10:58 on July 2nd 2015&amp;quot; but also missing a calendar system, so you can&amp;#39;t really tell what the month is etc. The important point is that it&amp;#39;s not just time-zone-less, but it&amp;#39;s actually &lt;em&gt;local&lt;/em&gt; - so it doesn&amp;#39;t represent a single instant in time. Unlike every other concept in Noda Time, I haven&amp;#39;t thought of any good analogy between &lt;code&gt;LocalInstant&lt;/code&gt; and the real world.&lt;/p&gt;  &lt;p&gt;Now, I don&amp;#39;t like having types I can&amp;#39;t describe easily, and I&amp;#39;d &lt;em&gt;love&lt;/em&gt; to just get rid of it completely... but it&amp;#39;s actually an incredibly powerful concept to have in the library. Not for &lt;em&gt;users&lt;/em&gt; of course, but for the &lt;em&gt;implementation&lt;/em&gt;. It&amp;#39;s spattered all over the place. Okay, the next best step to removing it is to hide it away from consumers: let&amp;#39;s make it internal. Unfortunately, that doesn&amp;#39;t work either, because it&amp;#39;s referred to in interfaces all the time too. For example, almost &lt;em&gt;every&lt;/em&gt; member of &lt;code&gt;ICalendarSystem&lt;/code&gt; has &lt;code&gt;LocalInstant&lt;/code&gt; as one of its parameters.&lt;/p&gt;  &lt;h3&gt;The rules around interfaces&lt;/h3&gt;  &lt;p&gt;Just to recap, every member of an interface - even an internal interface - is implicitly public. That causes some interesting restrictions. Firstly, every type referred to in a public interface must be public. So this would be invalid:&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="Modifier"&gt;internal&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;struct&lt;/span&gt; LocalInstant {}     &lt;br /&gt;    &lt;br /&gt;&lt;span class="InlineComment"&gt;// Doesn&amp;#39;t compile: Inconsistent accessibility&lt;/span&gt;     &lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;interface&lt;/span&gt; ICalendarSystem     &lt;br /&gt;{&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; LocalInstant GetLocalInstant(&lt;span class="ValueType"&gt;int&lt;/span&gt; year, &lt;span class="ValueType"&gt;int&lt;/span&gt; month, &lt;span class="ValueType"&gt;int&lt;/span&gt; day);     &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;So far, so good. It&amp;#39;s entirely reasonable that a public member&amp;#39;s declaration shouldn&amp;#39;t refer to an internal type. Calling code wouldn&amp;#39;t understand what &lt;code&gt;LocalInstant&lt;/code&gt; was, so how could it possibly use &lt;code&gt;ICalendarSystem&lt;/code&gt; sensibly? But suppose we only wanted to declare the interface internally. That should be okay, right? Indeed, the compiler allows the following code:&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="Modifier"&gt;internal&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;struct&lt;/span&gt; LocalInstant {}     &lt;br /&gt;    &lt;br /&gt;&lt;span class="InlineComment"&gt;// Compiles with no problems&lt;/span&gt;     &lt;br /&gt;&lt;span class="Modifier"&gt;internal&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;interface&lt;/span&gt; ICalendarSystem     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; LocalInstant GetLocalInstant(&lt;span class="ValueType"&gt;int&lt;/span&gt; year, &lt;span class="ValueType"&gt;int&lt;/span&gt; month, &lt;span class="ValueType"&gt;int&lt;/span&gt; day);     &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;But hang on... isn&amp;#39;t &lt;code&gt;GetLocalInstant&lt;/code&gt; public? That&amp;#39;s what I said earlier, right? So we&amp;#39;re declaring a public member using an internal type... which we thought wasn&amp;#39;t allowed. Is this a compiler bug?&lt;/p&gt;  &lt;p&gt;Well, no. My earlier claim that &amp;quot;a public member&amp;#39;s declaration shouldn&amp;#39;t refer to an internal type&amp;quot; isn&amp;#39;t nearly precise enough. The important aspect isn&amp;#39;t just whether the member is declared public - but its &lt;em&gt;accessibility domain&lt;/em&gt;. In this case, the accessibility domain of &lt;code&gt;ICalendarSystem.GetLocalInstant&lt;/code&gt; is only the assembly, which is why it&amp;#39;s a valid declaration.&lt;/p&gt;  &lt;p&gt;However, life becomes fun when we try to &lt;em&gt;implement&lt;/em&gt; &lt;code&gt;ICalendarSystem&lt;/code&gt; in a public class. It&amp;#39;s perfectly valid for a public class to implement an internal interface, but we have some problems declaring the method implementing &lt;code&gt;GetLocalInstant&lt;/code&gt;. We can&amp;#39;t make it a public method, because at that point its accessibility domain would be anything referring to the assembly, but the accessibility domain of &lt;code&gt;LocalInstant&lt;/code&gt; itself would still only be the assembly. We can&amp;#39;t make it internal, because it&amp;#39;s implementing an interface member, which is public.&lt;/p&gt;  &lt;p&gt;There &lt;em&gt;is&lt;/em&gt; an alternative though: explicit interface implementation. That comes with all kinds of other interesting points, but it does at least compile:&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="Modifier"&gt;internal&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;struct&lt;/span&gt; LocalInstant {}     &lt;br /&gt;    &lt;br /&gt;&lt;span class="Modifier"&gt;internal&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;interface&lt;/span&gt; ICalendarSystem     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; LocalInstant GetLocalInstant(&lt;span class="ValueType"&gt;int&lt;/span&gt; year, &lt;span class="ValueType"&gt;int&lt;/span&gt; month, &lt;span class="ValueType"&gt;int&lt;/span&gt; day);     &lt;br /&gt;}     &lt;br /&gt;    &lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; GregorianCalendarSystem : ICalendarSystem     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// Has to be implemented explicitly&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; LocalInstant ICalendarSystem.GetLocalInstant(&lt;span class="ValueType"&gt;int&lt;/span&gt; year, &lt;span class="ValueType"&gt;int&lt;/span&gt; month, &lt;span class="ValueType"&gt;int&lt;/span&gt; day);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// Implementation &lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;}&lt;/div&gt;  &lt;p&gt;So, we&amp;#39;ve got &lt;em&gt;somewhere&lt;/em&gt; at this point. We&amp;#39;ve managed to make a type used within an interface internal, but at the cost of making the interface itself internal, and requiring explicit interface implementation within any public classes implementing the interface.&lt;/p&gt;  &lt;p&gt;That could potentially be useful in Noda Time, but it doesn&amp;#39;t solve our real &lt;code&gt;LocalInstant&lt;/code&gt; / &lt;code&gt;ICalendarSystem&lt;/code&gt; problem. We need &lt;code&gt;ICalendarSystem&lt;/code&gt; to be public, because consumers need to be able to specify a calendar when they create an instance of &lt;code&gt;ZonedDateTime&lt;/code&gt; or something similar. Interfaces are just too demanding in terms of publicity.&lt;/p&gt;  &lt;p&gt;Fortunately, we have another option up our sleeves...&lt;/p&gt;  &lt;h3&gt;Abstract classes to the rescue!&lt;/h3&gt;  &lt;p&gt;I should come clean at this point and say that generally speaking, I&amp;#39;m an interface weenie. Whenever I need a reusable and testable abstraction, I reach for interfaces by default. I have a general bias against concrete inheritance, including abstract classes. I&amp;#39;m probably a little too harsh on them though... particularly as in this case they do everything I need them to.&lt;/p&gt;  &lt;p&gt;In Noda Time, I definitely &lt;em&gt;don&amp;#39;t&lt;/em&gt; need the ability to implement ICalendarSystem and derive from another concrete class... so making it a purely abstract class will be okay in those terms. Let&amp;#39;s see what happens when we try:&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="Modifier"&gt;internal&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;struct&lt;/span&gt; LocalInstant {}&amp;#160; &lt;br /&gt;    &lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;abstract&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; CalendarSystem     &lt;br /&gt;{&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;internal&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;abstract&lt;/span&gt; LocalInstant GetLocalInstant(&lt;span class="ValueType"&gt;int&lt;/span&gt; year, &lt;span class="ValueType"&gt;int&lt;/span&gt; month, &lt;span class="ValueType"&gt;int&lt;/span&gt; day);     &lt;br /&gt;}&amp;#160; &lt;br /&gt;    &lt;br /&gt;&lt;span class="Modifier"&gt;internal&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; GregorianCalendarSystem : CalendarSystem     &lt;br /&gt;{&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;internal&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;override&lt;/span&gt; LocalInstant GetLocalInstant(&lt;span class="ValueType"&gt;int&lt;/span&gt; year, &lt;span class="ValueType"&gt;int&lt;/span&gt; month, &lt;span class="ValueType"&gt;int&lt;/span&gt; day)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// Implementation&lt;/span&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&amp;#160; &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;Hoorah! Now we&amp;#39;ve hidden away &lt;code&gt;LocalInstant&lt;/code&gt; but left &lt;code&gt;CalendarSystem&lt;/code&gt; public, just as we wanted to. We could make &lt;code&gt;GregorianCalendarSystem&lt;/code&gt; public or not, as we felt like it. If we want to make any of &lt;code&gt;CalendarSystem&lt;/code&gt;&amp;#39;s abstract methods public, then we can do so provided they don&amp;#39;t require any internal types. There&amp;#39;s on interesting point though: types outside the assembly can&amp;#39;t derive from &lt;code&gt;CalendarSystem&lt;/code&gt;. It&amp;#39;s a little bit as if the class only provided an internal constructor, but with a little bit more of an air of mystery... you can override every method you can actually &lt;em&gt;see&lt;/em&gt;, and still get a compile-time error message like this:&lt;/p&gt;  &lt;div class="code"&gt;OutsideCalendar.cs(1,14): error CS0534: &amp;#39;OutsideCalendar&amp;#39; does not implement inherited abstract member   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;#39;CalendarSystem.GetLocalInstant(int, int, int)&amp;#39; &lt;/div&gt;  &lt;p&gt;I can just imagine the author of the other assembly thinking, &amp;quot;But I can&amp;#39;t even &lt;em&gt;see&lt;/em&gt; that method! What is it? Where is it coming from?&amp;quot; Certainly a case where the documentation needs to be clear. Whereas it&amp;#39;s impossible to create an interface which is &lt;em&gt;visible&lt;/em&gt; to the outside world but can&amp;#39;t be &lt;em&gt;implemented&lt;/em&gt; externally, that&amp;#39;s precisely the situation we&amp;#39;ve reached here.&lt;/p&gt;  &lt;p&gt;The abstract class is a little bit like an authentication token given by a single-sign-on system. From the outside, it&amp;#39;s an opaque item: you don&amp;#39;t know what&amp;#39;s in it or how it does its job... all you know is that you need to obtain it, and then you can use it to do other things. On the inside, it&amp;#39;s much richer - full of useful data and members.&lt;/p&gt;  &lt;h3&gt;Conclusion&lt;/h3&gt;  &lt;p&gt;Until recently, I hadn&amp;#39;t thought of using abstract classes like this. It would possibly be nice if we &lt;em&gt;could&lt;/em&gt; use interfaces in the same way, effectively limiting the implementation to be in the declaring assembly, but letting the interface itself (and some members) be visible externally.&lt;/p&gt;  &lt;p&gt;A bigger question is whether this is a good idea in terms of design anyway. If I &lt;em&gt;do&lt;/em&gt; make &lt;code&gt;LocalInstant&lt;/code&gt; internal, there will be a lot of interfaces which go the same way... or become completely internal. For example, the whole &amp;quot;fields&amp;quot; API of Noda Time could become an implementation detail, with suitable helper methods to fetch things like &amp;quot;how many days are there in the given month.&amp;quot; The fields API is an elegant overall design, but it&amp;#39;s quite complicated considering the very limited situations in which most callers will use it.&lt;/p&gt;  &lt;p&gt;I suspect I will try to go for this &amp;quot;reduced API&amp;quot; for v1, knowing that we can always make things more public later on... that way we give ourselves a bit more flexibility in terms of not having to get everything right first time within those APIs, too.&lt;/p&gt;  &lt;p&gt;Part of me still feels uncomfortable with the level of hiding involved - I know other developers I respect deeply who hide as little as possible, for maximum flexibility - but I &lt;em&gt;do&lt;/em&gt; like the idea of an API which is really simple to browse.&lt;/p&gt;  &lt;p&gt;Aside from the concrete use case of Noda Time, this has proved an interesting exercise in terms of revisiting accessibility and the rules on what C# allows.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1779234" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Wacky+Ideas/default.aspx">Wacky Ideas</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Noda+Time/default.aspx">Noda Time</category></item></channel></rss>