***** D method override mechanisms borked ******

kris foo at bar.com
Sat Jun 24 16:04:15 PDT 2006


Lars Ivar Igesund wrote:
> kris wrote:
> 
> 
>>Used to be that overriding methods in subclasses had some logic to it.
>>Now? Well, who knows:
>>
>>1) you can override a protected method and make it public. Doh!
>>
>>2) you can override a public method and make it private ... ok, but get
>>this -- the overload is not virtual -- it doesn't "actually" overload at
>>all. Very sneaky bug in the making, especially when the base class is
>>altered just slightly.
>>
>>3) to fix #2 let's use the override keyword! Yay! That will ensure we're
>>actually overriding the base class method instance! Well, it compiles,
>>but does *not* override. Bork Bork Bork.
>>
>>And so on, ad infinitum.
>>
>>This was not a problem at some distant point in the past. Now the rules
>>are (a) too murky for this simple dude to even comprehend and (b)
>>apparently thoroughly broken. The behaviour turns D into a land-mine for
>>both the unwary and for the seasoned professional. How to turn people
>>away from D in one easy lesson.
>>
>>Please, please, please revert whatever cleverness was injected there and
>>make it work in a clear, precise, /obvious/, and above all, *dependable*
>>manner. Heck, make the "override" keyword mandatory if you need to. The
>>latter should at least work, or cause a compie-time error.
> 
> 
> I couldn't agree more, and make sure the rules are thouroughly documented!
>  

Before Bruno gives me a ticket for terminology abuse, I should note that 
the use of "overload" in #2 was completely unintentional. One should at 
least wake up properly before getting one's daily dose of D frustration.

I seriously hope this is all just a mistake/bug/whatever, which will be 
fixed quickly and appropriately. However ...

The original behaviour limited the exposure of an overridden method to 
be less than or equal to the exposure of the original. For example, 
protected could not be made public via an override. The compiler would 
give you an error if you attempted to do so. The compiler used to 
prevent you from intercepting a superclass method where the original 
intent (of the designer) was that said method whould be internal usage 
only. For example, final, package, or private methods.

Now, you can intercept all you like. The compiler does not give an error 
at all. The following example illustrates a litany of places where the 
compiler should halt. Just ask yourself how one is supposed to design 
superclass functionality that should not be exposed, overridden or 
otherwise subverted by a subclass?


extern(C) int printf (char*, ...);

class Super
{
         protected void fu()
         {
                 printf ("super fu\n");
         }

         package void bar()
         {
                 printf ("super bar\n");
         }

         private void snafu()
         {
                 printf ("super snafu\n");
         }

         private void fu1()
         {
                 printf ("super fu\n");
         }

         final void bar1()
         {
                 printf ("super bar\n");
         }

         final private void snafu1()
         {
                 printf ("super snafu\n");
         }
}


class Sub : Super
{
	// illegal: exposing a protected method
         public void fu()
         {
                 printf ("sub fu\n");
         }

	// illegal: exposing a package method
         public void bar()
         {
                 printf ("sub bar\n");
         }

	// illegal: exposing a private method
         public void snafu()
         {
                 printf ("sub snafu\n");
         }

	// illegal: "override" a private method
         private override void fu1()
         {
                 printf ("sub fu1\n");
         }

	// illegal: "override" a final method
         private override void bar1()
         {
                 printf ("sub bar1\n");
         }

	// illegal: override & expose a final private method
         public void snafu1()
         {
                 printf ("sub snafu1\n");
         }
}


void main()
{
         auto s = new Sub;

         s.fu;
         s.bar;
         s.snafu;
         s.fu1;
         s.bar1;
         s.snafu1;
}


output:

sub fu
sub bar
sub snafu
sub fu1
sub bar1
sub snafu1


Basically, several well-known and fundamental OO tenets no longer exist 
in D; I personally have over two years of carefully designed libraries 
that are now little more than trash because of this (any subclass can 
now intercept any type of method implementation). Would imagine others 
are in the same boat.

Anyone who's ever tried to provide "read only" or immutable class 
implementation, particularly to make multi-threaded code so much more 
deterministic, can kiss that goodbye ... let's all wave together :/



More information about the Digitalmars-d-bugs mailing list