Virtual Extension By Inversion of Responsibility
Pavel Minaev
int19h at gmail.com
Sat Jun 12 23:15:16 PDT 2010
In case it is of interest...
Visual C# has had a somewhat similar feature, called "extension methods",
since version 3.0 (released in 2008).
By and large, it is just syntactic sugar that translates an instance member
invocation to a static member invocation. It does not use any special syntax
to distinguish the call, and so it looks identical to a normal invocation -
if a method with a given name (roughly speaking; in practice, this involves
overload resolution) is not found in the static type of the receiver, it
looks for an "equivalent" accessible static method, with the first argument
- corresponding to receiver - of a matching type, and decorated with
[ExtensionAttribute], in all accessible static classes in open or imported
namespaces. C# furthermore provides syntactic sugar for the attribute.
Overall, this looks like this:
// The original library interface
public interface IEnumerable<T> {
IEnumerator<T> GetEnumerator();
}
// Third-party extension library
namespace Foo {
public static class EnumerableExtensions {
public static IEnumerable<T> Filter(this IEnumerable<T> seq,
Func<T, bool> predicate) { // "this" is syntactic sugar for
[ExtensionAttribute]
...
}
}
}
// Client code
using Foo; // brings extension method definition into scope
class Program {
static void Main() {
IEnumerable<int> xs;
xs.GetEnumerator(); // normal method invocation
xs = xs.Filter(x => x > 0); // extension method invocation;
translated to:
xs = EnumerableExtensions.Filter(xs, x => x > 0);
}
}
More detailed coverage and examples are available here:
http://msdn.microsoft.com/en-us/library/bb383977.aspx
and here is a typical library class providing extension methods:
http://msdn.microsoft.com/en-us/library/system.linq.enumerable_members.aspx
The main issue is the same - the inability for a particular implementation
of the interface to "override" an extension method. For example, the .NET
base class library has a number of stock extension methods for
IEnumerable<T> interface - the usual set of operations on sequences,
filter/map/fold/zip etc. Among them are e.g. Count() - count of elements in
the sequence; and ElementAt() - retrieval of element by its index; which for
a generic sequence are only implementable by enumerating elements until the
desired one (or the end, for Count), which is O(n). Quite obviously, most
collections would be able to provide an O(1) Count(), and some would be able
to provide O(1) ElementAt(). However, there is no way they can do so in
practice, since the method call is static, and not overridable.
.NET class library cheats there - the implementations of Count() and
ElementAt() are tightly coupled to interfaces such as ICollection<T> (which
can provide O(1) count) and IList<T> (which can provide O(1) indexing) - and
simply check if the receiver implements those interfaces, and use a more
optimal branch if that is the case. But this all is hardcoded into the
extension methods - if you come up with your own interface, you won't be
able to plug it into that system.
That said, it is technically still possible to make such a system
extensible, if you couple every individual static extension method with a
corresponding single-method interface, and make the implementation of that
extension method to first check if the receiver implements that interface,
and delegate to the method on that interface if available. Then, any class
that needs to "override" the extension method just implements the
corresponding interface. In practice, though, this scheme is very
cumbersome, and I haven't ever seen it actually being used.
In contrast, the scheme being discussed for Java allows classes to override
default implementations of interface methods with minimal effort - from
programmer's perspective, it looks exactly like an override of a base class
method.
On Sat, Jun 12, 2010 at 10:10 PM, Paul Benedict <pbenedict at apache.org>wrote:
> Can anyone tell me if C# is trying to do something similar in their
> language? Or any language? It seems like a novel idea to me, but
> please forgive me not being a language expert.
>
> Paul
>
> On Sat, Jun 12, 2010 at 5:27 PM, Pavel Minaev <int19h at gmail.com> wrote:
> > This seems to be largely identical to C# extension methods. The problem
> with
> > it is that it misses the important use case of classes implementing
> > interfaces with extension methods being able to override the generic
> > implementations of those methods with their own (presumably optimized)
> > implementation.
> >
> > On Sat, Jun 12, 2010 at 2:56 PM, Collin Fagan <collin.fagan at gmail.com
> >wrote:
> >
> >> Hi Everyone,
> >>
> >> I've put together a draft of a document that postulates an alternate
> >> implementation of virtual extension methods.
> >>
> >> http://www.box.net/shared/r24vvgma5p
> >>
> >> I welcome any feedback.
> >>
> >> Thanks,
> >>
> >> Collin
> >>
> >>
> >
> >
>
More information about the lambda-dev
mailing list