The Non-Virtual Interface idiom in D

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Sat Sep 26 11:35:18 PDT 2009


Yigal Chripun wrote:
> On 25/09/2009 23:49, Andrei Alexandrescu wrote:
>> In this article:
>>
>> http://www.gotw.ca/publications/mill18.htm
>>
>> Herb Sutter makes a powerful argument that overridable functions
>> (customization points) should actually not be the same as the publically
>> available interface. This view rhymes with the Template Method pattern
>> as well.
>>
>> This leads to the interesting setup in which an interface should ideally
>> define some signatures of to-be-defined functions, but disallow client
>> code from calling them. For the clients, the same interface should
>> expose some higher-level final functions.
>>
>> Ignoring for the moment access protection semantics in D (which are
>> broken anyway), let's say this would work:
>>
>> interface Cloneable(T) if (is(T == class))
>> {
>> private T doClone(); // must implement but can't call
>> T clone() // this is what everybody can call
>> {
>> auto result = doClone();
>> assert(typeof(result) == typeof(this));
>> assert(this.equals(result));
>> return result;
>> }
>> }
>>
>> So clients must implement doClone, but nobody can ever call it except
>> Cloneable's module. This ensures that no cloning ever gets away with
>> returning the wrong object.
>>
>> Pretty powerful, eh? Now, sometimes you do want to allow a derived class
>> to call the base class implementation. In that case, the interface
>> function must be protected:
>>
>> interface ComparableForEquality(T)
>> {
>> protected bool doEquals(T);
>> final bool equals(T rhs)
>> {
>> auto result = doEquals(rhs);
>> assert(rhs.equals(cast(T) this) == result);
>> return result;
>> }
>> }
>>
>> The difference is that now a derived class could call super.doEquals.
>>
>> This feature would require changing some protection rules, I think for
>> the better. What do you think?
>>
>>
>> Andrei
> 
> to clarify your suggestion above I have a few questions:
> are the functions with definitions always final?
> 
> interface A {
>    final func () {...}
> }
> interface B {
>    final func () {...}
> }
> 
> class C : A, B {...}
> auto obj = new C;
> C.func(); // what happens here?

I think that would be a compile-time ambiguity error.

Andrei



More information about the Digitalmars-d mailing list