Jump to page: 1 2
Thread overview
When does final mean "maybe, kinda, sorta" ?
Jan 22, 2007
kris
Jan 23, 2007
kris
Jan 23, 2007
Sean Kelly
Jan 23, 2007
Sean Kelly
Jan 23, 2007
Sean Kelly
Jan 23, 2007
Frits van Bommel
Jan 23, 2007
John Reimer
Jan 23, 2007
kris
Jan 23, 2007
Sean Kelly
Jan 23, 2007
kris
Jan 23, 2007
Sean Kelly
Jan 23, 2007
Steve Horne
Jan 23, 2007
kris
Jan 23, 2007
Steve Horne
Jan 23, 2007
kris
Jan 24, 2007
Steve Horne
January 22, 2007
"That's a great deal to make one word mean," Alice said in a thoughtful tone. "When I make a word do a lot of work like that," said Humpty Dumpty, "I always pay it extra."


Reading one of Andrei's posts about const and final reminded me of what I consider to be a D wart. This is taken directly from the D reference manual:

"Functions marked as final may not be overridden in a derived class, unless they are also private."

Just how much does "final" get paid for this? Onto the given example:


<quote>

class A
{
    int def() { ... }
    final int foo() { ... }
    final private int bar() { ... }
    private int abc() { ... }
}

class B : A
{
    int def() { ... }	// ok, overrides A.def
    int foo() { ... }	// error, A.foo is final
    int bar() { ... }	// ok, A.bar is final private, but not virtual
    int abc() { ... }	// ok, A.abc is not virtual, B.abc is virtual
}

void test(A a)
{
    a.def();	// calls B.def
    a.foo();	// calls A.foo
    a.bar();	// calls A.bar
    a.abc();	// calls A.abc
}

void func()
{   B b = new B();
    test(b);
}

</quote>


1) You had to read that at least twice, didn't you? :)

2) Seems to me the usage of "final" here is entirely misleading, and opens up a lurking hole for some poor sod to break their ankle in.

3) the example (from the ref manual) highlights overriding of private and private-final methods. Surely this applies only within module scope? That is, within the same module? Assuming that's the case, why would any sane engineer do such a thing instead of changing the original class code? They have the source, obviously, and overriding private seems quite dubious at best. I can think of one case, but can't see why the language would need to support it explicitly.

In short, it appears the example exhibits some poor practice (overriding private methods), is somewhat misleading (one certainly *hopes* private cannot be seen beyond module-scope), and discusses how to make "final" mean something quite other than final.

How about fixing final? Or name it something more appropriate? It really shouldn't get paid any more than other keywords ...

- Kris
January 23, 2007
kris wrote:
[snip]
> In short, it appears the example exhibits some poor practice (overriding private methods), is somewhat misleading (one certainly *hopes* private cannot be seen beyond module-scope), and discusses how to make "final" mean something quite other than final.

I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm.

Andrei
January 23, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> kris wrote:
> [snip]
> 
>> In short, it appears the example exhibits some poor practice (overriding private methods), is somewhat misleading (one certainly *hopes* private cannot be seen beyond module-scope), and discusses how to make "final" mean something quite other than final.
> 
> 
> I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm.
> 
> Andrei

Good point. With D, however, the override itself would probably have to be within the same module as the Template Method?
January 23, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> kris wrote:
> [snip]
>> In short, it appears the example exhibits some poor practice (overriding private methods), is somewhat misleading (one certainly *hopes* private cannot be seen beyond module-scope), and discusses how to make "final" mean something quite other than final.
> 
> I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm.

It's a good design approach, but there's no reason the virtual methods must be private--they could be protected as well.  One could argue that the design is cleaner with the virtual methods private, but since the methods must be overridden by the derived class it's not like any protection attributes are being maintained anyway.  Isn't this a current topic of discussion on comp.l.c++.m? :-)


Sean
January 23, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> kris wrote:
> [snip]
> I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm.
> 
> Andrei

Design philosophy aside, what should be done about the issues with "final" itself?
January 23, 2007
Sean Kelly wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> kris wrote:
>> [snip]
>>> In short, it appears the example exhibits some poor practice (overriding private methods), is somewhat misleading (one certainly *hopes* private cannot be seen beyond module-scope), and discusses how to make "final" mean something quite other than final.
>>
>> I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm.
> 
> It's a good design approach, but there's no reason the virtual methods must be private--they could be protected as well.  One could argue that the design is cleaner with the virtual methods private, but since the methods must be overridden by the derived class it's not like any protection attributes are being maintained anyway.  Isn't this a current topic of discussion on comp.l.c++.m? :-)

There is a big difference between private and protected. Private means that later-added code cannot call the method, period. It could be said that private is "distantly more private" than both protected and public because both of the latter allow access by unbounded amounts of code.

So there is indeed something interesting by being required to implement something that you're not allowed to call. Something like Shirley Temple acting in movies she was too young to be allowed to watch :o).


Andrei
January 23, 2007
On Mon, 22 Jan 2007 15:31:25 -0800, kris <foo@bar.com> wrote:

>"Functions marked as final may not be overridden in a derived class, unless they are also private."
>
>Just how much does "final" get paid for this? Onto the given example:

...

>2) Seems to me the usage of "final" here is entirely misleading, and opens up a lurking hole for some poor sod to break their ankle in.

Having been in C++ mode for a bit, I'm probably misunderstanding the issue, but for what it's worth...

Aren't private members excluded from the virtual table? Early bound, in other words?

If so, one way to view it is that private methods cannot be overridden and are therefore inherently final, so it does no particular harm to actually say that they are final. Either requiring 'final' or banning it might help code consistency and readability, but it seems like a minor issue.

How can I say that a private method can't be overridden? Well, if there is no late binding, a new method with the same signature isn't really an override.

The private method doesn't really exist in any derived classes interface, internal or external. The only reason that derived classes are aware at all is to improve the compiler error messages. So any method added to a derived class with the same signature is just a completely new and independent method - not an override. It's really no different to having a method with the same signature in an unrelated class.

Potentially confusing enough to get a note in the documentation, maybe, but do we really want to ban derived classes from using certain method signatures just because they were used for private methods in the base class? That sounds like a violation of encapsulation to me. The derived classes shouldn't need to know about the private members of the base class at all, even for the purposes of avoiding name clashes. And adding a new private member to a base class should not break any derived classes that might happen to already use the same signature for a (private or public) method, especially since you may have no control or even knowledge of those derived classes.

Ah! you say, but we're talking about code in the same module. But then we get different rules for whether a derived class can define certain method signatures based on which module it happens to be in. Sure, you can rename the private methods in the base class to avoid a clash if you need to, but without reliable refactoring tools to catch all the calls, that can be potentially error-prone.

-- 
Remove 'wants' and 'nospam' from e-mail.
January 23, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> Sean Kelly wrote:
>> Andrei Alexandrescu (See Website For Email) wrote:
>>> kris wrote:
>>> [snip]
>>>> In short, it appears the example exhibits some poor practice (overriding private methods), is somewhat misleading (one certainly *hopes* private cannot be seen beyond module-scope), and discusses how to make "final" mean something quite other than final.
>>>
>>> I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm.
>>
>> It's a good design approach, but there's no reason the virtual methods must be private--they could be protected as well.  One could argue that the design is cleaner with the virtual methods private, but since the methods must be overridden by the derived class it's not like any protection attributes are being maintained anyway.  Isn't this a current topic of discussion on comp.l.c++.m? :-)
> 
> There is a big difference between private and protected. Private means that later-added code cannot call the method, period. It could be said that private is "distantly more private" than both protected and public because both of the latter allow access by unbounded amounts of code.
> 
> So there is indeed something interesting by being required to implement something that you're not allowed to call. Something like Shirley Temple acting in movies she was too young to be allowed to watch :o).

But you can call it, or even change its visibility:

class Base
{
private:
    virtual void fn() = 0;
};

class Derived : Base
{
public:
     virtual void fn() {}
    void call() { fn(); }
};

Sure, you can't call it through Base::fn(), but... :-)

I'll admit it's a clever design pattern, and one I use myself in C++, but I think there is also value in privates being implicitly final as in D.  No expressive power is really lost--the methods could be made protected just as easily--and I think it actually makes more conceptual sense that private functions cannot be overridden.


Sean
January 23, 2007
kris wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> kris wrote:
>> [snip]
>> I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm.
>>
>> Andrei
> 
> Design philosophy aside, what should be done about the issues with "final" itself?

I think the current design is consistent but potentially confusing.  If a function can be virtual (ie. if it is not private) then "final" controls whether it can be overridden.  So making a private function final is meaningless because it cannot be overridden--in this case, "final" is simply ignored.


Sean
January 23, 2007
Sean Kelly wrote:
> kris wrote:
> 
>> Andrei Alexandrescu (See Website For Email) wrote:
>>
>>> kris wrote:
>>> [snip]
>>> I agree about the misleading part, but I don't think that overriding private methods is poor practice. In fact I think it's rich practice :o). See e.g. http://www.gotw.ca/publications/mill18.htm.
>>>
>>> Andrei
>>
>>
>> Design philosophy aside, what should be done about the issues with "final" itself?
> 
> 
> I think the current design is consistent but potentially confusing.  If a function can be virtual (ie. if it is not private) then "final" controls whether it can be overridden.  So making a private function final is meaningless because it cannot be overridden--in this case, "final" is simply ignored.
> 
> 
> Sean

Fair enough. Then the compiler should be a tad smarter about disallowing 'stupid' combinations of attributes. This applies to many other attributes, not just final. People /will/ use whatever combination they're allowed to, and the doc appears to encourage them to do so.
« First   ‹ Prev
1 2