Interface Limitations in D

Elmar chrehme at gmx.de
Mon Sep 20 13:24:50 UTC 2021


On Monday, 20 September 2021 at 08:32:46 UTC, Alexandru Ermicioi 
wrote:
> On Sunday, 19 September 2021 at 20:00:11 UTC, Elmar wrote:
>> * **`interface`s do not permit overriding defaults**
>>
>>   D's interfaces don't allow default implementations of static 
>> and non-static functions unlike Java. This makes class 
>> implementations more verbose and promotes code duplication 
>> because you need to repeat the default implementation in every 
>> implementing class, even if you don't care.
>> 
>>   ...
>> 
>>   Abstract classes are no replacement because, first, you 
>> cannot inherit multiple abstract classes and, second, abstract 
>> classes implement partial incomplete behaviour while 
>> interfaces don't implement behaviour.
>
> You can use mixin template that will contain default 
> implementation of an interface.
>
> You can also declare final functions in interfaces, which can 
> partially serve for first case mentioned.
>
> Best regards,
> Alexandru

Thanks, Alexandru. Final functions won't do it however, if you'd 
like to override the given implementation in classes.

---

I want to add: after writing the post I found phobos-functions 
`autoImplement`, `blackHole` and `whiteHole` in `std.typecons` 
which automatically implement interface methods in some way.

Providing default implementation support seems not more difficult:

```D
mixin Interface!("MyInterface",
q{
     static immutable PI = 3.141592f;
     default static immutable CONSTANT = 0.0f;

     float toImplement(string s);

     default float isDefaulted()
     {
         return (CONSTANT ^^ PI) % toImplement(r"tau"));
     }
});
```

Providing default method implementations without code duplication 
and too much verbosity could work by defining the default method 
implementations as **compile-time token strings**. The above 
would generate

```D
interface MyInterface
{
     final static immutable PI()
     {
         return 3.141592f;
     }
     static immutable CONSTANT();
     enum DEFAULT_CONSTANT = q{{
         return 0.0f;
     }};

     float toImplement(string s);

     float isDefaulted();
     enum DEFAULT_isDefaulted =
     q{{
         return (CONSTANT ^^ PI) % toImplement(r"tau"));
     }};
}
```

Then people can either `mixin (DEFAULT_foo)` explicitly (in the 
class implementation) or use something like `mixin 
DefaultImplement!MyInterface;` to automatically implement missing 
DEFAULT_... token strings.

The solution is artificial but a limited simplistic 
implementation could use (compile-time) regex for this.

RegEx:
I don't know, whether D's engine would support matching balanced 
braces but my feeling assumes no. And the documentation 
description confirms myself. Simplicity over expressivity makes 
it harder to do the job with Regex and which might be 
disappointing for programmers from the scripting realm. I'd find 
a PCRE engine more practical. Worst-Case Performance does not 
matter if you know how to avoid the worst-case.



More information about the Digitalmars-d mailing list