June 03, 2013
Am 03.06.2013 18:16, schrieb Manu:
> On 3 June 2013 18:11, deadalnix <deadalnix@gmail.com
> <mailto:deadalnix@gmail.com>> wrote:
>
>     On Monday, 3 June 2013 at 07:30:56 UTC, Kapps wrote:
>
>         On Monday, 3 June 2013 at 07:06:05 UTC, Manu wrote:
>
>             There are functions that
>             the author intended to be overridden, and functions that
>             have no business
>             being overridden, that the author probably never imagined
>             anyone would
>             override.
>             What if someone does come along and override one of these,
>             and it was never
>             designed to work under that circumstance in the first place?
>             At very least, it will have never been tested. That's not a
>             very robust API
>             offering if you ask me.
>
>
>         This is something just as important as the performance issues.
>         Most of the time people will leave functions to simply use
>         whatever the default is for virtual/final. If it's final, this
>         works fairly well. The author hasn't put in the effort to decide
>         how to handle people overriding their function. But with virtual
>         by default, you don't know if the author actually considered
>         that people will be overriding the function or if it's simply
>         that they didn't bother specifying. I know the vast majority of
>         my code is virtual, simply because I didn't specify the 'final'
>         keyword 500 times, and didn't think about that I'd need to do
>         it. The resulting code is unsafe because I didn't consider those
>         functions actually being overridden.
>
>
>     The whole concept of OOP revolve around the fact that a given class
>     and users of the given class don't need to know about its subclasses
>     (Liskov's substitution principle). It is subclass's responsibility
>     to decide what it override or not, not the upper class to decide
>     what is overriden by subclasses.
>
>
> Then OOP is fundamentally unsafe, because the author will never consider
> all the possibilities!
>
>     If you want to create a class with customizable parts, pass
>     parameters to the constructor. This isn't OOP what OOP is about.
>
>
> Eh?
>
>     The performance concern is only here because things has been smashed
>     together in a inconsequent way (as it is often done in D). In Java
>     for instance, only overriden function are actually virtual.
>     Everything else is finalized at link time.
>
>
> Java is not compiled. If you compile Java code, all functions are
> virtual always.

That depends, http://www.excelsior-usa.com/jet.html

June 03, 2013
The virtual vs. non-virtual thing doesn't really matter that much. We're talking about a 5% performance difference here, at most. You just type 'final' a little bit here and there when you're near the end of writing our your class hierarchy and get a little performance boost.
June 03, 2013
On Monday, 3 June 2013 at 16:16:48 UTC, Manu wrote:
> Java is not compiled. If you compile Java code, all functions are virtual
> always.

Java is JIT compiled and function that aren't overriden are finalized automatically by the JIT compiler.

It's even able to virtualize at runtime if an override is finally linked, or the other way around, refinalize.

We could do that in D as LTO, as long as we have a way to tell the compiler if a function can be overriden in a shared object.
June 03, 2013
On 2013-06-03, 20:00, w0rp wrote:

> The virtual vs. non-virtual thing doesn't really matter that much. We're talking about a 5% performance difference here, at most. You just type 'final' a little bit here and there when you're near the end of writing our your class hierarchy and get a little performance boost.

5%? Not when the function you call in an inner loop is virtual. I see up
to a 100% time increase for simple functions.

-- 
Simen
June 03, 2013
On Monday, 3 June 2013 at 16:59:43 UTC, Andrei Alexandrescu wrote:
> It is trivial. To paraphrase a classic: "I'm not taking away your ability to make everything final, you can type 'final:' as much as you like."
>

Wont we at least need 'virtual:' for the inverse of 'final:'?

June 03, 2013
Am 03.06.2013 20:00, schrieb w0rp:
> The virtual vs. non-virtual thing doesn't really matter that much. We're
> talking about a 5% performance difference here, at most. You just type
> 'final' a little bit here and there when you're near the end of writing
> our your class hierarchy and get a little performance boost.

Personally I don't care.

I learned OOP with Turbo Pascal and C++, both use static by default.

After that I lost count how many OO languages I have used since those days, each with its pluses and minus.

Since I only use D for playing around outside work, I'll just go with what the real D users decide for the language.

--
Paulo
June 03, 2013
On Monday, 3 June 2013 at 16:16:48 UTC, Manu wrote:
> It's impossible in D with separate compilation, and dynamic libraries seal
> the deal.

Not really. It will be possible the very moment (if) "export" gets strict so that everything not marked with "export" won't be available for outer world.
June 03, 2013
On 4 June 2013 02:59, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org>wrote:

> On 6/3/13 12:25 PM, Manu wrote:
>
>> You won't break every single method, they already went through that
>> recently when override was made a requirement.
>> It will only break the base declarations, which are far less numerous.
>>
>
> That's what I meant.
>
>
>  How can you justify the change to 'override' with a position like that?
>> We have already discussed that we know PRECISELY the magnitude of
>> breakage that will occur.
>> It is: magnitude_of_breakage_from_**override /
>> total_number_of_derived_**classes. A much smaller number than the
>> breakage
>> which was gladly accepted recently.
>>
>
> Well it's kinda too much relativism that the number of breakages is considered small because it's smaller than another number.
>
>
>  And the matter is far from trivial.
>>
>
> It is trivial. To paraphrase a classic: "I'm not taking away your ability to make everything final, you can type 'final:' as much as you like."


You read my posts where I illustrate how going virtual is a one-way ride
right?
You can safely change to virtual, but you can't go from virtual back to
final.
Aside from the performance hazards, and the empirical evidence from
watching C++ programmers use D, virtual-by-default has the dangerous
potential to lock you in to an awkward situation where you can never safely
make a change to fix something that should never have been that way in the
first place.

 In fact, if you think this is
>> trivial, then how did the override change ever get accepted? That is most certainly trivial by contrast, and far more catastrophic in terms of breakage.
>>
>
> That's a completely different issue, so this part of the argument can be considered destroyed.


Rubbish. A similar set of considerations apply, and there's an awful lot more supporting this one in addition.


June 03, 2013
On Monday, June 03, 2013 22:15:15 Dicebot wrote:
> On Monday, 3 June 2013 at 16:16:48 UTC, Manu wrote:
> > It's impossible in D with separate compilation, and dynamic
> > libraries seal
> > the deal.
> 
> Not really. It will be possible the very moment (if) "export" gets strict so that everything not marked with "export" won't be available for outer world.

1. That'll only affect Windows unless we change the linking model on *nix systems.

2. That'll only affect stuff that isn't exported from a shared library. There are plenty of cases where a class is exported from a shared library, and it has lots of functions on it which are supposed to be non-virtual.

3. Doesn't doing this require that the _linker_ optimize out the virtuality of the functions for you? If that's the case, it won't work any time soon (if ever), because we use the C linker, not our own.

So, I really don't think that it makes sense to say that export is going to fix much of anything with regards to virtuality.

- Jonathan M Davis
June 04, 2013
On Monday, June 03, 2013 19:06:53 David Nadlinger wrote:
> On Monday, 3 June 2013 at 16:25:24 UTC, Manu wrote:
> > You won't break every single method, they already went through
> > that recently when override was made a requirement. […] A much
> > smaller number than the breakage
> > which was gladly accepted recently. […] how did the override
> > change ever get accepted […]
> 
> It appears as if either you have a interesting definition of "recently", or you are deliberately misleading people by bringing up that point over and over again.
> 
> According to http://dlang.org/changelog.html, omitting "override" produced a warning since D 2.004, which was released back in September 2007! Granted, it was only actually turned from a deprecation warning into an actual deprecation in 2.061 (if my memory serves me right), but it's mostly a flaw in the handling of that particular deprecation that it stayed at the first level for so long. The actual language change was made – and user-visible – almost six (!) years ago, which is a lot on the D time scale.

Except that because it was only treated as a warning until very recently and because dmd has the abnormal behavior of not printing warnings by default, plenty of folks weren't using override until quite recently.

> You are also ignoring the fact that in contrast to requiring "override", there is no clean deprecation path for your proposal, at least as far as I can see: Omitting the keyword started out as a warning, and IIRC still is allowed when you enable deprecated features via the compiler switch. How would a similar process look for virtual-by-default? As far as am isolated module with only a base class is concerned, this is not question of valid vs. invalid code, but a silent change in language semantics.

The change in semantics isn't very silent at all thanks to override. It actually breaks quite loudly. Historically, the steps to do it would have been something like

1. Print a message or warning that a function which is being overridden isn't marked as virtual.

2. Deprecate overriding a function which is not marked as virtual.

3. Make it an error to override a function which isn't marked as virtual and then actually make it so that functions which are not marked as virtual are non-virtual.

But now that deprecations don't stop compilation by default anymore, we might even be able to skip the first step and do

1. Deprecate overriding a function which is not marked as virtual.

2. Make it an error to override a function which isn't marked as virtual and then actually make it so that functions which are not marked as virtual are non-virtual.

And the only functions which have to be changed are those which are actually being overridden, and the compiler will already give an error when you override a function without marking the overriding function with override, so programmers are already forced to mark all of the functions that care whether the base class function is virtual or not. So, you won't be getting silent breakage. It's more of a problem when a library writer puts an API in their library and does not actually override it themselves (even if it's intended to be overridden), as it's the users of that library which will see the deprecation warnings and eventual breakage, but the library writer should be testing their own stuff, and the users of the library can yell at them about it.

So, the breakage is minimal and noisy, but it _is_ still breakage. If we were starting from scratch, I really don't think that there would be much excuse for not making functions non-virtual by default given that we require overriding functions to be marked with override, but it is more of an open question when we're this far into the game. I still think that it's worth making the change though.

- Jonathan M Davis