Retroactive Interfaces - Strong Duck Typing
Posted: 11/28/2007 3:28:39 AM
Anyone who has read about
Ruby may have heard about
Duck Typing;
it allows any object to be passed into a method as long as the object
has the properties/methods used by the originating method. If this were
to be implemented in C# it would look something like:
public void Blah(object foo)
{
Console.WriteLine(foo.Bar);
Console.WriteLine(foo.Kung("Jackie Chan"));
}
And
it would work completely fine at run-time as long as the object passed
to the Blah method had a property called "Bar" and a method called
"Kung" that took in a string as an argument. Unfortunately this won't
work in C# because C# is a strongly typed language, "object" simply
does not have a "Bar" property, nor a "Kung" method. Strong typing does
have its advantages though, IntelliSense and compile time checking. If
in Ruby you were to call the Blah method and it didn't have the
appropriate properties and methods you would receive a run-time error.
Run-time errors are bad because they make end-users cranky, which makes
your boss cranky, which makes you cranky.
Strongly typed
languages can have some of the benefits of this flexibility with
Interfaces. Just create an IFoo interface with the needed properties
and you're off to the races, right? Well, yeah, but only on objects
that you have the ability to edit, which leaves you praying that the
authors of your dependencies have your
bizarre perfectly reasonable needs in mind (not likely).
For
instance, I recently wrote a windows component that would listen for
some events on a textbox and process the results. The only problem is I
wanted to let the user hook up the component to either a TextBox or a
ToolStripTextBox. Since those objects don't share a common interface, I
have to have two separate properties on the component, a TextBox and a
ToolStripTextBox and at run-time I have to throw an error if the user
assigned a value to both properties (and remember, run-time error !=
desirable).
What I propose is the natural extension (pun intended) of
Extension Methods
-> Retroactive Interfaces. Simply put, I'd like to be able to tell
the compiler that certain classes implement an interface, but do so
from the interface, not from the class (because I may not be able to
edit the class). I don't really care what the exact syntax is but I
could imagine it going something like:
using System.Windows.Forms;
public Interface IText ImplementedBy TextBox, ToolStripTextBox
{
string Text { get; set; }
event EventHandler TextChanged;
}
This
is if you wanted to be fairly precise about which classes implemented
your new interface, but it would be also nice if to tell the compiler
that you wanted any object that has the appropriate
properties/methods/events to have it implement said interface. Such
syntax could look like:
public Interface IText ImplementedByAllAppropriate { ... }
And voilĂ , you now have the flexibility of Duck
Typing and the compile time checking and IntelliSense of Strong Typing.
I know bureaucracy can be a wildly beast, so
Anders,
if you're reading, I'm willing to grease proverbial wheels with
$2,000,000 to get this feature in the next version of C#. (No, I don't
have the $2,000,000 right now, but I'm working out a very lucrative
deal with a rich Nigerian General)
Post Script: Like Extension Methods, Retroactive Interfaces aren't aimed at solving some unsolvable problem. You can definitely use the
Adapter Pattern
to wrap up the object and have the adapter class implement the needed
interface. But lets be honest, its simply a pain in the ass, it takes
time to write the adapter class and you have to explicitly create an
adapter for every class you want to implement your interface
(ImplementedByAllAppropriate, isn't really possible with an adapter). A
Retroactive Interface is some syntatic sugar aimed at making developers
lives easier.
Tags: Wishlist