Reply to dsimcha,
Several people have griped in the past that D class methods are
virtual by default. I've pointed out to them that you can get around
this by making the methods final. However, this is a bit of a blunt
instrument, because some use cases for a single class may call for
polymorphism and other use cases for the same class may call for fast
performance and no polymorphism. A possible solution is, given a
class:
class Foo {
// Actual implementation.
}
final class FooFinal : Foo{
// Dummy that just makes Foo final.
}
And then, when you need performance and not polymorphism, you would
invoke FooFinal instead of Foo. However, this requires manual
forwarding of constructors and bloats the name space. A simple
syntactic sugar solution to this dilemma that would add very little
complexity to the language would be to allow final to describe a class
instance, as well as a class. The following would apply to a final
instance:
1. Method calls don't need to be virtual.
2. An instance of a subclass cannot be converted to a final instance
of the
base class.
3. A final instance can be implicitly converted to a non-final
instance, but
the opposite would not work.
Using final as an instance attribute like this would also allow
another useful
feature: Storing class instances inline in arrays, structs, or other
classes.
Basically, by marking a class instance as final, you'd be telling the
compiler that you do not need and are not using polymorphism in this
case,
even if the class hierarchy uses it for other use cases, and
therefore, all relevant optimizations can be made.
You can't make an instance final without creating a new type (code bloat)
because even if you can generate non virtual calls into the object, interior
calls will still be virtual. One solution to this would be to rerun the code
gen for the classes methods (and all base class methods) without virtual
calls.
OTOH you could do that for even non-final types: generate a set of methods
with (where possible) non-virtual internal calls (that could require re-running
the code gen on base class methods) that is used only for this class and
a set with virtual calls for types that derive from it. This would result
in a lot more code but it could (depending on usage) be a lot faster code.