I don't know how is in JAVA, but if you assert here that declaring a method
as *sealed* si the same as declaring non-virtual method you are wrong. Such
a method is still virtulal.
No it's not.
A a = new C()
a.f() calls C.f()
Isn't it virtual?
A.f is virtual,but C.f isn't, because you can't override it in a class
that derives from C.
If it wasn't it would call A.f()
Nope. From the C# specification again:
<quote>
The implementation of a virtual member can be changed by an overriding
member in a derived class.
</quote>
Now, can you override f() in a class derived directly from C? No? Then
it's not virtual.
*sealed* modifier force you to stop using overriden until you don't use
*virtual* again and then you can continue override the method.
You can never override the actual sealed method. You can hide it with
another virtual method and then override *that*, but that's not
actually overriding the sealed (non-virtual) method.
BTW the
compiler generates *callvirt* instruction as a evidence of that the method
is indeed *virtual*
That's evidence of A.f() being virtual, not evidence of C.f() being
virtual.
In c# you can keep going with overrideing the method which was sealed.
No you can't.
what
you have to is to declared it as virtual again(to start new virtual
implemetation).
You also have to declare it as "new" and *hide* the previous method.
That's *not* overriding it.
That is posible because when CLR decides, which is most-derived method it
doesn't take into account only the runtime type of the object it kind of
takes into account the type of the variable as well.
The CLR doesn't take that into account; the compiler does.
To be more strict
callvirt is provided with the name of the class from where to start looking
for the most-derived implementation.
Yes, but it will stop when it gets to a sealed method. In other words,
there's no way that you can write a class MyDerivedClass such that
C c = new MyDerivedClass();
c.f();
will call anything other than c.f();
(assuming you don't change C itself).
If you think you can, please demonstrate it.
When you put *sealed* modifier for a method you have to put override as well
(other wise it does'n make sence to prohibit overriding of something which
cannot be overrided anyway).
Indeed, but that's irrelevant.
The modifier *override* already means that the method is virtual.
No, it means the method in the class it's deriving from is virtual.
If you read further down the same section you will find example of hiding
virtual methods, which is more closely to what happend when you declare a
method as a *sealed*. *sealed* modifier just force you to hide the method if
you want to change the implementation.
That doesn't change the implementation though - it just provides a new
method. It doesn't change the implementation in the same way that
overriding does.
If *final* in JAVA means that the method cannod be overriden or hid then it
is different form the non-virtual methods.
It's different from C# due to the fact that you can't hide it, but that
doesn't mean it's non-virtual. You can't hide it just because you can't
hide methods at all in Java. If we were to apply your logic above, we'd
also come to the conclusion that there aren't any virtual methods in
Java either, as they can't be hidden. Do you really believe that every
method in Java is neither virtual nor non-virtual?
Non-virtual methods cannot be overriden - OK. One can hide then, though.
You don't *have* to be able to hide them in order for them to be non-
virtual though! Hiding's just a different concept in the same area.
So my question is: Why C# allows virtual methods to be hidden. Isn't it
error prone.
Not really, because there's a warning message if you try to do it.
I believe that the best is:
1. To have virtual and non-virtual methods.
Which both C# and Java have.
2. Sealing virtual methods has to prevent further overriding and hiding the
methods.
I disagree with this - a warning is all that's required to avoid
hiding. Sealing an otherwise virtual method makes it non-virtual, and
that's all that's required.
And actually I think I know the answer. It is side efect of the way the CLR
resolves wich is the most-derived method. .NET is cross langage platform and
if C# was preventing this using calsses written in other languges (allowing
hiding virtual methods) would put C# programmers to consfusion.
I don't think that was the reason at all. I think it was to prevent
classes from breaking when they're recompiled against newer versions of
libraries they may use. You get a warning if you try to hide a member
(because the member may not have existed before), but you get the same
behaviour, and can remove the warning by explicitly saying that that's
what you wanted to do. Don't forget that this method may itself be part
of a public API which can't easily be changed.