On Tuesday, 3 December 2013 at 18:10:43 UTC, Dejan Lekic wrote:
This is *a radical change*, and instead of "(unknown) people agreed" the community deserves a better explanation why are we switching to final as default storage class...

Let me state in advance that I believe that in most situations people will leave the default option unless they have reason to (that is, stick with the virtual unless they have reason to mark something final, or stick with final unless they have reason to mark something virtual). For virtual, there is often less reason to realize something should be final as things look like they work until much later. Forgetting to stick a 'final' in front of your function will never give you a compiler error. That being said, some pros / cons of virtual/final by default. Obviously heavily biased.

1) The most obvious reason is final has better performance. Some effort can be taken to reduce the impact of virtual methods but ultimately there will always be a performance hit. In a large program, this may not be too substantial a hit. I consider this the weakest argument for final-by-default, but others who attempt to deliver as efficient as possible code consider it very important.

2) A function that is virtual cannot be changed to be final without breaking existing code. If you are writing a library and have a virtual method which you wish to change to final, anyone using that library that overrides your method will have their code break and require substantial design changes if they were relying on simply being able to override your method. If a method was final and is changed to be virtual later on, no code will break unless the developer then decides to change it back to final afterwards.

3) Related to the above, if a method is not virtual there is nothing you can do about it. A method might be perfectly capable of being virtual without issues, yet if the developer forgot to mark it as 'virtual' you cannot override it even though it may be safe to do so.

4) If we assume that the statement about people sticking with the default is true (which I strongly believe it is, yet lack actual data for), final by default means more 'virtual' keywords being stuck everywhere. For a language that may already be considered to have too many modifiers to stick in front of your methods, this would add yet another one for many class methods.

5) Marking something virtual is a huge commitment and makes substantial guarantees about implementation details. A simple example is a property. Making a property virtual is a statement that you will never access the field behind the property (assuming there is one), as someone may have overridden the property to use a different backing field or a constant value. This is something that requires actual acknowledgement, yet virtual by default does not require you to think about this as it's automatically virtual. This is actually a mistake I catch myself making not infrequently.

A less obvious example is add vs addRange. If you implement a class to extend an existing collection yet add capabilities for storing length by overriding add/remove to increase/decrease length, should you override addRange and add range.length? What if something then overrides addRange for more efficient adding of multiple elements rather than calling add N times, or something that only sometimes calls add depending on the element type or state? These are considerations that require actual thought, and while simply adding a "virtual" keyword to them doesn't mean you thought about the implications, the very action of having to add this keyword makes it a conscious effort and so helps you consider the side-effects of adding it and what it means.


I don't understand how virtual-by-default is even considered for new languages. It provides slight convenience while being error prone. Yet breaking almost every single D program is a huge issue and stability is something that D is desperately trying to achieve. I'd like virtual by default, but it's a hard sell now. I wouldn't mind updating my code for this and I feel it better to do this sort of change now rather than later when more/larger code uses D, but it is still a substantial code break. If it was actually done it would need a transition flag or such to help the process (final by default normally, virtual by default with the transition flag), and likely a virtual keyword implemented well ahead of time so people could start making their changes early and gradually.

Reply via email to