February 17, 2012
On 02/17/2012 03:00 PM, kenji hara wrote:
> I think this is a current implementation problem.
>
> In this case, just `override void foo()` in class D should override
> the method in C.
> And `void foo()const` should be a new overlodad of foo.
>
> Kenji Hara
>

Walter has stated that this is by design.

http://d.puremagic.com/issues/show_bug.cgi?id=3757
February 17, 2012
Forget it... auto (or super) override doesn't help much anyway.
February 17, 2012
> No. Absolutely not. I hate the fact that C++ does this with virtual. It makes
> it so that you have to constantly look at the base classes to figure out what's
> virtual and what isn't. It harms maintenance and code understandability. And
> now you want to do that with @safe, pure, nothrow, and const? Yuck.

It's different from virtual. Virtual is an implicitly inherited loosening attribute
while @safe, pure, nothrow and const are restricting.

It could be potentially confusing when introducing new overloads.
But that is also detected easily.

class Base
{
    void foo() const
    {
    }
}

class Derived : Base
{
    override void foo()
    {
    }

    void foo() const
    {
    }
}
February 17, 2012
On 02/17/2012 03:25 PM, Piotr Szturmaj wrote:
> Forget it... auto (or super) override doesn't help much anyway.

It is clearly a bug though.
February 17, 2012
On Friday, 17 February 2012 at 03:24:50 UTC, Jonathan M Davis wrote:
> No. Absolutely not. I hate the fact that C++ does this with virtual. It makes it so that you have to constantly look at the base classes to figure out what's virtual and what isn't. It harms maintenance and code understandability. And now you want to do that with @safe, pure, nothrow, and const? Yuck.
>
> I can understand wanting to save some typing, but I really think that this harms code maintainability. It's the sort of thing that an IDE is good for. It does stuff like generate the function signatures for you or fill in the attributes that are required but are missing.

Besides the fact that not everyone uses an IDE, my other counter-argument to these "the IDE generates your boilerplate" arguments is that code is read and modified more often than it is written.  I don't like reading or modifying boilerplate code any more than I like writing it.  Besides, if you're using a fancy IDE, can't it show you the protection attributes inherited from the derived class?
February 17, 2012
Am 17.02.2012, 05:10 Uhr, schrieb H. S. Teoh <hsteoh@quickfur.ath.cx>:

> On Thu, Feb 16, 2012 at 07:41:00PM -0800, Walter Bright wrote:
>> On 2/16/2012 7:23 PM, Jonathan M Davis wrote:
>> >No. Absolutely not. I hate the fact that C++ does this with virtual.
>> >It makes it so that you have to constantly look at the base classes
>> >to figure out what's virtual and what isn't. It harms maintenance and
>> >code understandability. And now you want to do that with @safe, pure,
>> >nothrow, and const? Yuck.
>>
> It's probably the same reason I brought up: looking at a function's
> definition will no longer tell you which modifiers are actually in
> effect. So you have to trace the overrides up the inheritance hierarchy
> in order to know exactly what modifiers it has.
>
> On that note, though, one thing I've always wanted in a programming
> language is to be able to ask the compiler to expand all templates,
> deduce all types, etc., for a given function/declaration, and print out
> what it actually understands the declaration to be (as opposed to what I
> *think* the declaration would expand to).

Depending on how people approach the language
- editor or IDE
- looking up documentation or relying on intuitive code
- prefer explicit or implicit declarations (see 'auto' return as well)
- trust in the compiler catching their errors or trying to keep compilers
  out of their understanding of the source code
we come to different strong opinions.

If @safe, pure, nothrow, and const were inherited and optional now I would try that system, but still wonder if it actually makes me use these attributes more than before. I tend to just put @safe: at the top of my module and mark trivial I/O functions @trusted. Frankly I don't mind the typing as much as I minded to have to remove these attributes later, because after a few nested function calls I ended up calling a throwing function (and don't want to catch). I think similar things happened with pure and const. It helps that I wouldn't have to go through all of the class hierarchy if this happens, but I wonder what the benefit of pure and nothrow is. @safe and const help me detect bugs or design mistakes. If there were performance benefits to using strongly pure functions, I'd be far more tempted to use them than with automatic inheritance. Also the case for Phobos was mentioned, but that are mostly free functions that wouldn't benefit from inheritance either.

My utopical IDE would deduce all the attributes from looking at the source code and actually place them in the code like this:

	uint foo() /*deduced:*/ pure const nothrow @safe
	{
		return 42;
	}

This way I see what the method currently evaluates to, but I am free to add a "throw new Exception(...);" with the IDE changing the signature on the fly:

	uint foo() /*deduced:*/ pure const @safe
	{
		throw new Exception("abc");
	}

If the attributes could be displayed as some sort of tri-state buttons in the code view and I would decide that this method *has to be* const, I would click on 'const' to move the keyword left:

	uint foo() const /*deduced:*/ pure @safe
	{
		throw new Exception("abc");
	}

And at this point no user of that IDE could be too lazy to add "pure const nothrow", because it would be deduced from the code and also put in the signature to document it. Editor purists will hate this idea and it doesn't solve anything right *now*, but I wanted to share it anyway. Maybe it inspires others to come up with better ideas.

-- Marco
February 17, 2012
Agreed. Timon, could you please submit to bugzilla?

BTW I referred to the converse problem:

class C {
  void foo() {}
  void foo() const {}
}

class D : C {
  void foo() const {} // should only override the const overload
}


Andrei

On 2/17/12 8:00 AM, kenji hara wrote:
> I think this is a current implementation problem.
>
> In this case, just `override void foo()` in class D should override
> the method in C.
> And `void foo()const` should be a new overlodad of foo.
>
> Kenji Hara
>
> 2012/2/17 Timon Gehr<timon.gehr@gmx.ch>:
>> On 02/17/2012 02:33 PM, Timon Gehr wrote:
>>>
>>>
>>> Introducing a new overload against const in a subclass is illegal:
>>>
>>> class C{
>>>      void foo(){}
>>> }
>>> class D : C{
>>>      override void foo(){}
>>>      override void foo()const{}
>>> }
>>>
>>> Error: D.foo multiple overrides of same function
>>
>>
>> Oops...
>>
>> I meant
>>
>>
>> class C{
>>     void foo(){}
>> }
>>
>> class D:C{
>>     override void foo(){}
>>     void foo()const{}
>> }
>>
>> The error message is the same though.

February 17, 2012
On 2/17/12 8:13 AM, kenji hara wrote:
> I think the lack of 'override' keyword (filed as bug 3836) should
> become an error, without the phase of deprecating it. Otherwise
> following case will be allowed.

Yes. Walter?

Andrei
February 17, 2012
On 2012-02-17 13:56, Iain Buclaw wrote:
> On 17 February 2012 07:42, Jacob Carlborg<doob@me.com>  wrote:
>>> OTOH, if ddoc could automatically fill in the effective qualifiers, then
>>> this will be a non-problem. ;-)
>>
>>
>> And if ddoc could show the inheritance hierarchy as well.
>>
>
> Jacob++

The ddoc generator in the Eclipse plugin Descent already does this. I'm wondering if it can be back ported to DMD or if it's completely separate.

-- 
/Jacob Carlborg
February 17, 2012
V Thu, 16 Feb 2012 18:49:40 -0800, Walter Bright wrote:

> Given:
> 
>      class A { void foo() { } }
>      class B : A { override pure void foo() { } }
> 
> This works great, because B.foo is covariant with A.foo, meaning it can "tighten", or place more restrictions, on foo.

Will the 'inheritance' of attributes work for interfaces too?

     interface I { void foo() @safe pure nothrow const; }
     class B : I { void foo() { } }  // is it @safe pure nothrow const ?