Re: non virtual interfaces

2013-09-20 Thread Alexandr Druzhinin

20.09.2013 23:09, Jonathan M Davis пишет:

You can use NVI with classes just fine just so long as you use protected rather
than private, but making it private there won't work either, because private
is never virtual (and it wouldn't really help you any if it were, because
while the base class private function might not be callable, the derived class
one would still be callable by the derived class, so trying to prevent the
virtual function in NVI from ever being called outside of the base class is
broken in the first place - including in C++ where it was originally devised).
What NVI helps with is making it so that the public function being called as
part of the API is non-virtual, allowing you to do stuff before and after the
hidden virtual function being called, but the derived classes can still call
their implementation of the hidden, virtual function.

- Jonathan M Davis


I see. Thanks for clarifying.


Re: non virtual interfaces

2013-09-20 Thread Jonathan M Davis
On Friday, September 20, 2013 22:40:48 Alexandr Druzhinin wrote:
> 20.09.2013 12:45, Ali Çehreli пишет:
> > On 09/19/2013 10:31 PM, Alexandr Druzhinin wrote:
> >  > if I use protected instead of private in interface like:
> > private member functions are non-virtual.
> 
> But I just use code example from TDPL russian edition. And TDPL says
> clearly that (un)transmogrify() are private and CardboardBox _maynot_
> make (un)transmogrify() non-private - this is highlighted as compiler
> support of NVI idiom. Is it wrong example, I guess?

TDPL is mostly correct but not completely correct. AFAIK, it has never been 
implemented that you can override private functions in interfaces like TDPL 
describes. With classes, package and private are _never_ virtual, so private 
will have be treated differently interfaces in order to do what TDPL describes. 
That may or may not be implemented in the future.

You can use NVI with classes just fine just so long as you use protected rather 
than private, but making it private there won't work either, because private 
is never virtual (and it wouldn't really help you any if it were, because 
while the base class private function might not be callable, the derived class 
one would still be callable by the derived class, so trying to prevent the 
virtual function in NVI from ever being called outside of the base class is 
broken in the first place - including in C++ where it was originally devised). 
What NVI helps with is making it so that the public function being called as 
part of the API is non-virtual, allowing you to do stuff before and after the 
hidden virtual function being called, but the derived classes can still call 
their implementation of the hidden, virtual function.

- Jonathan M Davis


Re: non virtual interfaces

2013-09-20 Thread Alexandr Druzhinin

20.09.2013 12:45, Ali Çehreli пишет:

On 09/19/2013 10:31 PM, Alexandr Druzhinin wrote:

 > if I use protected instead of private in interface like:

private member functions are non-virtual.
But I just use code example from TDPL russian edition. And TDPL says 
clearly that (un)transmogrify() are private and CardboardBox _maynot_ 
make (un)transmogrify() non-private - this is highlighted as compiler 
support of NVI idiom. Is it wrong example, I guess?


 > interface Transmogrifier
 > {
 >  final void thereAndBack()
 >  {
 >  transmogrify();
 >  untransmogrify();
 >  }
 >
 >  protected:
 >  void transmogrify();
 >  void untransmogrify();
 > }

If they were non-virtual (i.e. private), the calls to transmogrify() and
untransmogrify() from thereAndBack() would be bound to
Transmogrifier.transmogrify and Transmogrifier.untransmogrify at compile
time. That happens and the linker cannot find their definitions.

I see. Thanks, I understand it now better


 > class CardboardBox: Transmogrifier
 > {
 >  override protected void transmogrify() { }
 >  override void untransmogrify() {}
 > }

 > it compiles, but why does compiler permit making untransmogrify() be
 > public?

It is up to CardboardBox to decide whether untransmogrify() is public or
not. Note that untransmogrify() is still protected when objects are used
through the Transmogrifier interface. However, when an object is known
to be a CardboardBox so that it is being used through the CardboardBox
interface, it is not bound to be a Transmogrifier at that point. Yes,
CardboardBox inherits from Transmogrifier but it is CardboardBox's
interface that is being used at that point so it decides.
Thanks again. So there is no compiler support for NVI idiom? Because if 
CardboardBox may define its own (un)transmogrify() - TDPL says it 
possible only if (un)transmogrify() have other signatures.


 > How can I prohibit this? May be it just unrealized yet?

You cannot prohibit from Transmogrifier.

Ali


Unfortunately I tried to use NVI for it namely.


Re: non virtual interfaces

2013-09-19 Thread Ali Çehreli

On 09/19/2013 10:31 PM, Alexandr Druzhinin wrote:

> if I use protected instead of private in interface like:

private member functions are non-virtual.

> interface Transmogrifier
> {
>  final void thereAndBack()
>  {
>  transmogrify();
>  untransmogrify();
>  }
>
>  protected:
>  void transmogrify();
>  void untransmogrify();
> }

If they were non-virtual (i.e. private), the calls to transmogrify() and 
untransmogrify() from thereAndBack() would be bound to 
Transmogrifier.transmogrify and Transmogrifier.untransmogrify at compile 
time. That happens and the linker cannot find their definitions.


> class CardboardBox: Transmogrifier
> {
>  override protected void transmogrify() { }
>  override void untransmogrify() {}
> }

> it compiles, but why does compiler permit making untransmogrify() be
> public?

It is up to CardboardBox to decide whether untransmogrify() is public or 
not. Note that untransmogrify() is still protected when objects are used 
through the Transmogrifier interface. However, when an object is known 
to be a CardboardBox so that it is being used through the CardboardBox 
interface, it is not bound to be a Transmogrifier at that point. Yes, 
CardboardBox inherits from Transmogrifier but it is CardboardBox's 
interface that is being used at that point so it decides.


> How can I prohibit this? May be it just unrealized yet?

You cannot prohibit from Transmogrifier.

Ali



Re: non virtual interfaces

2013-09-19 Thread Alexandr Druzhinin

if I use protected instead of private in interface like:
interface Transmogrifier
{
final void thereAndBack()
{
transmogrify();
untransmogrify();
}

protected:
void transmogrify();
void untransmogrify();
}

class CardboardBox: Transmogrifier
{
override protected void transmogrify() { }
override void untransmogrify() {}
}

int main()
{
auto cb = new CardboardBox();
return 0;
}

it compiles, but why does compiler permit making untransmogrify() be 
public? How can I prohibit this? May be it just unrealized yet?


non virtual interfaces

2013-09-19 Thread Alexandr Druzhinin

Hello all.

I try to use NVI and failed with a snippet from TDPL:

interface Transmogrifier
{
final void thereAndBack()
{
transmogrify();
untransmogrify();
}

private:
void transmogrify();
void untransmogrify();
}

class CardboardBox: Transmogrifier
{
override private void transmogrify() { }
override void untransmogrify() {}
}

int main()
{
auto cb = new CardboardBox();
return 0;
}

doesn't compile with log info:
src/test.d(16): Error: function test.CardboardBox.transmogrify cannot 
override a non-virtual function
src/test.d(17): Error: function test.CardboardBox.untransmogrify does 
not override any function, did you mean to override 
'test.Transmogrifier.untransmogrify'?


It rather well differs from what I expected reading TDPL. Something is 
changed very much or I just missed something?


Re: Non-Virtual Interfaces

2011-03-04 Thread Aleksandar Ružičić
>
> 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..


Re: Non-Virtual Interfaces

2011-03-04 Thread Aleksandar Ružičić
>
> What you may want to consider is an abstract class instead of NVI, as long
> as you don't need multiple inheritance, it should be fine.
>
> -Steve
>

Well, I've decided to give NVI a try just because multiple inheritance
would be best way to do what I want (aldo I hate that feature of C++
and just don't use it) but it seems I can't do it with a NVI either...
So back to the drawing board for me :)

thanks for reply

- Aleksandar


Re: Non-Virtual Interfaces

2011-03-04 Thread Jonathan M Davis
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


Re: Non-Virtual Interfaces

2011-03-04 Thread Steven Schveighoffer
On Fri, 04 Mar 2011 05:17:00 -0500, 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?


The traditional explanation of NVI is that the final function is never  
virtual.  In your case, bar must be virtual at the IBase level, so it must  
go in the vtable.


I'm unsure whether this is intended to be a bug or a feature.

What you may want to consider is an abstract class instead of NVI, as long  
as you don't need multiple inheritance, it should be fine.


-Steve


Non-Virtual Interfaces

2011-03-04 Thread Aleksandar Ružičić
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?