Recommended ways to handle final classes

JS js.mdnq at gmail.com
Fri Aug 16 14:21:25 PDT 2013


On Friday, 16 August 2013 at 15:47:21 UTC, Joseph Rushton 
Wakeling wrote:
> On 08/16/2013 05:40 PM, JS wrote:
>> Can you describe how this helps?
>> 
>> Sure, if you use A the compiler should be able to optimize 
>> method calls but you
>> can't use A in inheritance because it is a final class. e.g.,
>
> The point is, you should be able to use _A for inheritance, A 
> for performance,
> and they both have the same functionality.
>
> Or am I mistaken?

You can't get them both at the same time though, which you might 
just make _A final.


The whole point of inheritance is to treat derived classes as if 
they were base classes.

e.g., code was designed to use class _A, you come along, extend 
_A to A, but "trick" to the code to use your A(even though it 
thinks it's an _A).

Now, when you use your final class A where _A's are suppose to 
be, there can be no optimization made by the compiler(unless it 
can determine the object really is an A).

e.g.,

class _A { void foo() { writeln(); } }
final class A : _A { }

...

_A a = new A;
...
a.foo(); // can't be inlined because a's type is not CT final.

A aa = new A;
...
aa.foo(); // can be inlined because aa's type is final(no need 
for vtable)

The only difference is that a is _A and aa is A.


So when you use your final class with inheritance, it becomes 
useless because it gets treated as the base class, which is not 
final.

When one does

_A a = new A;

a is of type _A regardless of what we actually stick in a as far 
as what the compiler see's(unless it's real smart but then, final 
is not needed).

A final class is simply to stop someone from deriving from it. 
The compiler can make optimizations based on this info IF it 
knows that the object is from a final type.


Here is a more real world example


class Shape { }
final class fShape : Shape { }
class Rectangle : Shape { }
final class fRectangle : Rectangle { }

Shape s = new fRectangle; // useless, just use Rectangle, the 
compiler will probably never know s is an fRectangle. (it might 
in some cases but probably not worth it)

That is the oop way, this is not:

fShape s = new fRectangle; // invalid, fRectangle is not derived 
from fShape.
// compiler knows s is a final class and can make optimizations 
on it.


Because we can't assign concrete shapes to fShape(because they 
have to derive from them, but can't because the class is final), 
it becomes useless to use(no way to do oop).


To do oop you have to have derivation from base classes, but 
final stops that. Hence your two goals(being able to use oop and 
being able not to(using final) are mutually exclusive).


The only way it can be useful is if the compiler can determine if 
an object is final at compile time... but if it can do this then 
it doesn't need to be final in the first place(it will still be 
able to inline methods).




More information about the Digitalmars-d-learn mailing list