March 04, 2011
On Friday, March 04, 2011 02:17:00 Aleksandar Ružičić wrote:
> I'm trying to use NVI idiom but i keep getting errors from dmd.
> 
> This is my setup:
> 
> module test;
> 
> import std.stdio;
> 
> interface IBase {
> 	void foo();
> 	void bar();
> }
> 
> interface IBar : IBase {
> 	final void bar() {
> 		writefln("IBar.bar()");
> 	}
> }
> 
> class Foo : IBar {
> 
> 	void foo() {
> 		writefln("Foo.foo()");
> 	}
> }
> 
> void main() {
> 
> 	Foo foo = new Foo();
> 	foo.foo();
> }
> 
> When I try to compile it i get "test.d(16): Error: class test.Foo interface function IBar.bar isn't implemented"
> 
> And if I try to define bar() in Foo i receive "test.d(22): Error:
> function test.Foo.bar cannot override final function
> IBar.test.IBar.bar"
> which is expected since IBar.bar() is final.
> 
> So, am I missing some point about NVIs here or is it just not yet implemented in dmd?

In NVI, you have a public, non-virtual function which calls a private one which is then overridden by a derived class (or in this case, a class which implements the interface). So, the API is non-virtual, but the functionality is overridden. It gives you the ability to enforce that certain things happen when the function is called (such as checking something about the parameters or enforcing that a set of functions are always called in a particular order), but the actual functionality is still overridden.

In D, the public function would have to be final to make it non-virtual/non- overridable, and the function it calls would have to be protected, since you can't override private functions ( http://d.puremagic.com/issues/show_bug.cgi?id=4542 ). In this case, you're trying to override final functions, which doens't work at all.

However, if you're not trying to do anything other than call the implemented function (you're certainly not here), then there's no point to NVI. Just use a normal, public interface function or make the base class of your class abstract and put the function's declaration there.

- Jonathan M Davis
March 05, 2011
>
> In D, the public function would have to be final to make it non-virtual/non- overridable, and the function it calls would have to be protected, since you can't override private functions ( http://d.puremagic.com/issues/show_bug.cgi?id=4542 ). In this case, you're trying to override final functions, which doens't work at all.
>

Well I don't try to override final function, I know it cannot be done :) I've just tried to override bar() in Foo when compiler told me that I don't have that function implemented and I received message that it cannot be overriden, as I've expected..

> However, if you're not trying to do anything other than call the implemented function (you're certainly not here), then there's no point to NVI. Just use a normal, public interface function or make the base class of your class abstract and put the function's declaration there.
>
> - Jonathan M Davis
>

That was just an example, what was my goal was is to have setup like this:

interface IEvent {
   EventType type();
}

interface IEventListener {
   void handle(IEvent event);
}

class MyEvent : IEvent {

   this(bool flag) {
     this.flag = flag;
   }

   EventType type() {
     return EventType.MyEvent;
   }

   bool isFlag() {
     return flag;
   }

   private:
      bool flag;
}

interface IMyEventListener : IEventListener {
    void onFlag(MyEvent event);
    void onNotFlag(MyEvent event);

    final void handle(IEvent event) {

       MyEvent e = cast(MyEvent) event;

       if (e !is null) {
         if (e.isFlag()) {
            onFlag(e);
         } else {
            onNotFlag(e);
         }
       }
    }
}

which would allow me to have a class that can listen for different events at the same time, but it seems that to be able to do that I'd have to move handling routine into the event class..