February 26, 2012
On Friday, 17 February 2012 at 02:49:40 UTC, 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. But:
>
>     class A { pure void foo() { } }
>     class B : A { override void foo() { } }
>
> fails, because B.foo tries to loosen the requirements, and so is not covariant.
>
> Where this gets annoying is when the qualifiers on the base class function have to be repeated on all its overrides. I ran headlong into this when experimenting with making the member functions of class Object pure.
>
> So it occurred to me that an overriding function could *inherit* the qualifiers from the overridden function. The qualifiers of the overriding function would be the "tightest" of its explicit qualifiers and its overridden function qualifiers. It turns out that most functions are naturally pure, so this greatly eases things and eliminates annoying typing.
>
> I want do to this for @safe, pure, nothrow, and even const.
>
> I think it is semantically sound, as well. The overriding function body will be semantically checked against this tightest set of qualifiers.
>
> What do you think?

I'm still not convinced about this apply to const.  Consider this example:

Initial code:
class A{
  void foo(int) const;
  void foo(float) const;
}
class B{
  alias A.foo foo;
  override void foo(int);
}


Revision to class A:
class A{
  void foo(int);
  void foo(int) const;
  void foo(float);
  void foo(float) const;
}

When the user recompiles, there will be no errors or warnings.  All uses of foo(int) through a const B will revert to using the base class's implementation.
February 26, 2012
On 02/26/2012 06:39 PM, Jason House wrote:
> On Friday, 17 February 2012 at 02:49:40 UTC, 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. But:
>>
>> class A { pure void foo() { } }
>> class B : A { override void foo() { } }
>>
>> fails, because B.foo tries to loosen the requirements, and so is not
>> covariant.
>>
>> Where this gets annoying is when the qualifiers on the base class
>> function have to be repeated on all its overrides. I ran headlong into
>> this when experimenting with making the member functions of class
>> Object pure.
>>
>> So it occurred to me that an overriding function could *inherit* the
>> qualifiers from the overridden function. The qualifiers of the
>> overriding function would be the "tightest" of its explicit qualifiers
>> and its overridden function qualifiers. It turns out that most
>> functions are naturally pure, so this greatly eases things and
>> eliminates annoying typing.
>>
>> I want do to this for @safe, pure, nothrow, and even const.
>>
>> I think it is semantically sound, as well. The overriding function
>> body will be semantically checked against this tightest set of
>> qualifiers.
>>
>> What do you think?
>
> I'm still not convinced about this apply to const. Consider this example:
>
> Initial code:
> class A{
> void foo(int) const;
> void foo(float) const;
> }
> class B{
> alias A.foo foo;
> override void foo(int);
> }
>
>
> Revision to class A:
> class A{
> void foo(int);
> void foo(int) const;
> void foo(float);
> void foo(float) const;
> }
>
> When the user recompiles, there will be no errors or warnings. All uses
> of foo(int) through a const B will revert to using the base class's
> implementation.

This is by far not the only hijacking scenario enabled by using alias for merging in the parent's overload set. re-implementing the method and calling super is the only safe way to warrant hijacking protection.


3 4 5 6 7 8 9 10 11 12 13
Next ›   Last »