Wacky Ideas 2: Class interfaces

(Disclaimer: I’m 99% sure I’ve heard someone smarter than me talking about this before, so it’s definitely not original. I thought it worth pursuing though.)

One of the things I love about Java and C# over C/C++ is the lack of .h files. Getting everything in the right place, only doing the right things in the right files, and coping with bits being included twice etc is a complete pain, particularly if you only do it every so often rather than it being part of your everyday life.

Unfortunately, as I’ve become more interface-based, I’ve often found myself doing effectively the same thing. Java and C# make life a lot easier than C in this respect, of course, but it still means duplicating the method signatures etc. Often there’s only one implementation of the interface – or at least one initial implementation – but separating it out as an interface gives a warm fuzzy feeling and makes stubbing/mocking easier for testing.

So, the basic idea here is to extract an interface from a class definition. In the most basic form:

class interface Sample
{
    public void ThisIsPartOfTheInterface()
    {
    }
    
    public void SoIsThis()
    {
    }
    
    protected void NotIncluded()
    {
    }
    
    private void AlsoNotIncluded()
    {
    }
}

So the interface Sample just has ThisIsPartOfTheInterface and SoIsThis even though the class Sample has the extra methods.


Now, I can see a lot of cases where you would only want part of the public API of the class to contribute to the interface – particularly if you’ve got properties etc which are meant to be used from an Inversion of Control framework. This could either be done with cunning keyword use, or (to make fewer syntax changes) a new attribute could be introduced which could decorate each member you wanted to exclude (or possibly include, if you could make the default “exclude” with a class-level attribute).


So far, so good – but now we’ve got two types with the same name. What happens when the compiler runs across one of the types? Well, here’s the list of uses I can think of, and what they should do:


  • Variable declaration: Use the interface
  • Construction: Sse the class
  • Array declaration/construction: Use the interface (I think)
  • typeof: Tricky. Not sure. (Note that in Java, we could use Sample.class and Sample.interface to differentiate.)
  • Type derivation: Not sure. Possibly make it explicit: “DerivedSample : class Sample” or “DerivedSample : interface Sample
  • Generics: I think this would depend on the earlier “not sure” answers, and would almost certainly be complicated

As an example, the line of code “Sample x = new Sample();” would declare a variable x of the interface type, but create an instance of the concrete class to be its initial value.


So, it’s not exactly straightforward. It would also violate .NET naming conventions. Would it be worth it, over just using an “Extract Interface” refactoring? My gut feeling is that there’s something genuinely useful in here, but the complications do seem to overwhelm the advantages.


Perhaps the answer is not to try to have two types with the same name (which is where the complications arise) but to be able to explicitly say “I’m declaring interface ISample and implementing it in Sample” both within the same file. At that point it may be unintuitive to get to the declaration of ISample, and seeing just the members of it isn’t straightforward either.


Is this a case where repeating yourself is fundamentally necessary, or is there yet another way of getting round things that I’m missing?

6 thoughts on “Wacky Ideas 2: Class interfaces”

  1. It’s a good idea, but one I’m not so keen on. By having the interface defined in the class makes the class bulky and you could find yourself exposing things you’d not really wanted to. Also, anyone else having to read the code afterwards may find it harder. It all depends how you’d specify the interface. I’d be interested if you could maybe have some kind of nested portion of the class defining the interface that when the compiler encountered it, would under the hood create the interface for you.

    e.g.

    class Simple
    {
    interface ISimple
    {
    // put interface methods here…
    }

    // Continue with class definition here..
    }

    That way it becomes more readable and then we could use ISimple when necessary. It is something to think about as it can be a nightmare when you’re looking through layers and layers of files trying to find the details of interfaces that have been implemented in developerA’s code..

  2. It’s a bad idea and I fail to see the usefuless of it.
    It’s something that should be handled by the IDE not the language.

    Want to create an interface from a class?
    Right click > refactor > extract interface.

  3. An interesting ide, although I see some problems.

    First of all, it break the convention that interface name always start with “I”. That may not look like a big deal, but it is the sole coding convention that I’ve seen universally followed.

    On bigger issues, I wonder about it’s actual utility. If an interface and reference implementation are that closely aligned, one wonders if you are using interfaces properly. On th elast major project I worked on, an interface and it’s implementing class weren’t allowed in the same assembly.

    A more practical solution may be just a Perl script to take a class source file and extracted the interface. A more elaborate solution would take an assembly and use Reflection to extract the information to product the interface code. This would allow using [Attributes] for excluded properties. However, that leads to a chicken & egg problem: You’d need the interface to compile the class to get the assembly needed to produce the interface.

  4. “Using interfaces properly” is a fairly elastic concept, IMO. Even if there’s never going to be more than one production implementation, being able to swap that out and use a mock/stub when testing things that have the interface as a collaborator can be very useful.

    It’s also good, IMO, for making it clear what is really required of a collaborator. There may be various reasons to have public methods which aren’t required by the layer above, but by extracting the interface which is actually required, there’s a better warm fuzzy feeling about avoiding leakage.

    As Monkeyget says, the Extract Interface refactoring is probably the best “solution” – with the issues that you’ve repeated yourself (just not manually) and changes in one place require identical changes in another.

    Jon

  5. I don’t know that I like the idea too much, I actually expose interfaces in one assembly and implement in another

    but perhaps

    class interface : Whatever, IWhatever

  6. Imo, this is _almost_ a good idea because it would encourage programming against interfaces. You could even take it one step further and create a language that _forces_ you to program against an interface rather than an implementation, which would be a risky bet on some theoretical ideas–you’re betting that all implementers of the interface will follow the contract specified therein, among other things.

    One likely misuse of “class interfaces” is failing to write the interface and the class separately in cases where the class follows a more strict contract than should the interface. Another is failure to properly follow the original contract without use of the original code or private members. Then again, these are problems already existing. Providing the convenience to do something we often do anyway is, at worst, a temptation to use the convenience when it is inappropriate.

    I hope to have the chance to try “class interfaces” in an experimental language some day before passing any final judgement on the idea.

Comments are closed.