IanG on Tap

Ian Griffiths in Weblog Form (RSS 2.0)

Blog Navigation

April (2018)

(1 item)

August (2014)

(1 item)

July (2014)

(5 items)

April (2014)

(1 item)

March (2014)

(1 item)

January (2014)

(2 items)

November (2013)

(2 items)

July (2013)

(4 items)

April (2013)

(1 item)

February (2013)

(6 items)

September (2011)

(2 items)

November (2010)

(4 items)

September (2010)

(1 item)

August (2010)

(4 items)

July (2010)

(2 items)

September (2009)

(1 item)

June (2009)

(1 item)

April (2009)

(1 item)

November (2008)

(1 item)

October (2008)

(1 item)

September (2008)

(1 item)

July (2008)

(1 item)

June (2008)

(1 item)

May (2008)

(2 items)

April (2008)

(2 items)

March (2008)

(5 items)

January (2008)

(3 items)

December (2007)

(1 item)

November (2007)

(1 item)

October (2007)

(1 item)

September (2007)

(3 items)

August (2007)

(1 item)

July (2007)

(1 item)

June (2007)

(2 items)

May (2007)

(8 items)

April (2007)

(2 items)

March (2007)

(7 items)

February (2007)

(2 items)

January (2007)

(2 items)

November (2006)

(1 item)

October (2006)

(2 items)

September (2006)

(1 item)

June (2006)

(2 items)

May (2006)

(4 items)

April (2006)

(1 item)

March (2006)

(5 items)

January (2006)

(1 item)

December (2005)

(3 items)

November (2005)

(2 items)

October (2005)

(2 items)

September (2005)

(8 items)

August (2005)

(7 items)

June (2005)

(3 items)

May (2005)

(7 items)

April (2005)

(6 items)

March (2005)

(1 item)

February (2005)

(2 items)

January (2005)

(5 items)

December (2004)

(5 items)

November (2004)

(7 items)

October (2004)

(3 items)

September (2004)

(7 items)

August (2004)

(16 items)

July (2004)

(10 items)

June (2004)

(27 items)

May (2004)

(15 items)

April (2004)

(15 items)

March (2004)

(13 items)

February (2004)

(16 items)

January (2004)

(15 items)

Blog Home

RSS 2.0

Writing

Programming C# 5.0

Programming WPF

Other Sites

Interact Software

Implicit Interfaces, Dynamic vs Static Typing, and COM

Thursday 5 January, 2006, 08:24 PM

Martin Fowler recently posted an entry on Implicit Interface Implementation. The basic idea is that Java and C# both offer two kinds of 'interface' that you can program against. There's the kind explicitly declared with the interface keyword. And there's also the set of methods offered by a class - that is, in a sense, an 'interface'.

I put 'interface' in quotes because it's a different kind of a thing from an interface in the C# or Java language sense. The big difference being that the latter kind of interface is wholly abstract - any class can choose to implement an interface. But the members of a class are associated with the class that defines them. A method Foo.Bar is different from Quux.Bar. And only the class Foo, or classes derived from Foo can implement Foo.Bar

Fowler's proposed 'implicit interface' is essentially a proposal to allow any class to provide an implementation of Foo.Bar even if Foo is a class.

This is really just an expression of a limitation one runs into from time to time with Java and C#. It's a helpful way of looking at it because it provides an insight into the nature of the problem.

The problem is this: sometimes it's useful to be able to pass some piece of code a different kind of object from the type it was expecting; sometimes, you can't do this in Java or C#.

The most fashionable example of where this is useful is unit testing. For example, a couple of years ago I was working on some C# code that used MSMQ. Obviously I wanted my unit tests to run the relevant code without hooking it up to a real message queue. So it'd be useful to provide my own mock MessageQueue object in order to test the code in isolation.

The problem is that if I write code like this in C#:

public void UseQueue(MessageQueue q)
{
    q.Send("Hello!");
}

that code expects to be passed something that's an instance of the MessageQueue type. I won't be allowed to compile code that tries to pass in something else. If I were to write my code in raw IL to avoid type checking, it'll be unverifiable. I'm hosed because it wants to call MessageQueue.Send, not IansMockMessageQueue.Send.

Actually I'm not completely stuffed in this particular case. By lucky chance, MessageQueue derives from MarshalByRefObject. This means I can get the remoting infrastructure to cruft up a transparent proxy for me. A transparent proxy is something that looks and feels like the real type, but isn't. It's just a runtime-generated shim, and it does nothing but notify the code of your choosing whenever something tries to do something to the object.

(Java supports a similar trick - that's what Fowler is referring to when he mentions 'dynamic proxies' towards the end.)

But it's a bit of a hack. It doesn't seem like the most direct way of expressing that you want to pass something that has the same 'implicit interface' as MessageQueue.

Moreover, this hack isn't always available. (At least not in C#.) You can only create transparent proxies for things that derive from MarshalByRefObject. If you're dealing with a type that doesn't, then you really are out of luck.

Dynamic Languages Don't Have This Problem

With a dynamically typed language you wouldn't get this problem, because the UseQueue method above wouldn't be specific about what kind of object it required as a parameter - it'd take anything. And so long as whatever you pass in had a Send method. We could write C# code that behaves the same way:

public void UseQueue(object q)
{
    q.GetType().GetMethod("Send").Invoke(q, "Hello!");
}

(Yes, I know it's not quite the same. This is broken for overloaded Send methods. But the fix is as straightforward as it is tedious, so I decided not to clutter the example.)

This is sometimes known as 'duck typing'. Ostensibly because it's based on the principle that if it walks like a duck and quacks like a duck, it is a duck. But that's actually a bad analogy. The reality is closer to: "If it walks and quacks, that's close enough for me - who cares if it happens to be Dr. Nick Riviera?" (This is a big fallacy with duck typing: you're never checking whether the way in which it walks and quacks is in fact like a duck. But that's a topic for another blog entry.)

Advocates of dynamic languages are already pouncing on Fowler's post and claiming that it's indicative of the inherent superiority of dynamic languages.

But here's the thing...

It's Got Nothing To Do with Being Dynamic

COM doesn't suffer from this problem either. And nobody would accuse COM of being dynamically typed.

(Well, OK, yes, there's Automation, but I'm not talking about IDispatch here. I'm talking about proper COM with its high-fibre vtbls.)

In COM, Fowler's need for implicit interfaces would never arise because everything's an interface. If you want to use an object in COM you have to do so via an interface. So you're always able to make your own implementation.

So we have two opposite ends of the spectrum - COM and dynamic languages. Both of them avoid the issue. Clearly static typing wasn't the problem. So what is the problem with C# and Java?

Mixing Interface with Class Considered Harmful

The problem Fowler describes only arises if you comingle the concepts of interface and implementation.

COM avoids the problem because the only way you can use an object is through an interface type that has no association with any particular class. Dynamic languages avoid the problem by avoiding the notion of an interface type entirely. Java and C# suffer from this problem because you can use the class as a poor kind of interface, thus binding yourself to the implementation, or something derived from it.

If you're disciplined enough, you can avoid the problem: just because you can program against a class doesn't mean you have to. You can use COM-style interface-based programming if you like. It's just a lot of work, particularly when it comes to using system and 3rd party components - you end up having to define interfaces and write shims for all of them!

What Fowler is suggesting is essentially something that automates this work. When someone writes a class, all the class members are essentially private, but you get an auto-generated interface representing what would otherwise be public members.

This would then enable any class to implement, say, Duck.Walk, indicating that not only is it walking, but that it is walking like a duck, and can therefore be treated as a duck.

Dynamic typing isn't necessary. What's necessary is a clean separation of interface from implementation. Clearly we should all go back to using COM. :)

Copyright © 2002-2024, Interact Software Ltd. Content by Ian Griffiths. Please direct all Web site inquiries to webmaster@interact-sw.co.uk