Java vs. C# - Part 2 - Virtual Methods and Overload Resolution

Java vs. C# - Part 2 - Virtual Methods and Overload Resolution
   Here comes part 2 of the "Java vs C#" series. I still want to remind you to read part 0 and part 1 because they contain my motivation and important side notes but if you do not feel like reading them just remember that I only compare the C# and the Java language and claim that C# is better but do not compare the Java and .NET platforms and do not claim anything about the platforms as a whole (at least not in these articles). Read on to find out why Java's approach of letting methods be virtual by default is wrong.

   In Java methods are virtual by default and matching methods override base class methods by default. This can turn into a problem with versioning. Imagine that you have a class A and a class B that inherits from A and has a method void foo(). At some point a developer who has no idea about class B adds a method void foo() to class A. Then your class B overrides the method in A. This happens silently with no compiler error and possibly no runtime error but results in wrong behavior due to unintended polymorphism. This is really bad for maintainability and we already agreed in part 0 that maintainability is the most important goal of C# and Java.  

   On the other hand what if we wanted to have a method foo() in class A and override it in class B but someone changes the method name in A to bar()? Then the code would still compile despite the fact that the bar method is not overridden as intended. This makes refactoring and versioning harder.

   C# solves these problems by forcing virtual base methods to be marked with the virtual keyword and overriding method to be marked with the override keyword. This way no unintended behavior can be compiled and run without errors.

   Java designers have acknowledged and partially solved the second problem by introducing the @Override annotation in Java 6. However it is optional and as to my knowledge does not solve the first problem. Probably there are options in the compiler to make the @Override annotation mandatory for methods that override something but it is not on by default. Using annotation for something that should be a keyword hurts language consistency. If @Override is an annotation why is final a keyword? However annotation is probably the best decision in this legacy situation.

   Adding insult to injury virtual methods hurt performance (due to virtual dispatch) and developers just forget to seal them.

   More in depth commentary by Anders (Hallowed be His name!) himself can be found in this interview.

   In the C# language there are more cases of design targeted at maintainability and versioning. For example the overload resolution does not choose the best overload match in general but the best overload in the most derived class that has any match. This may not seem logical at first because developers expect the compiler to choose the best overload (as in Java) but prevents silent changes in program behavior when a better match is added to the base class. This is a good tradeoff because the developer surely will notice that his method does not behave right when he has just written it even if he does not know the language rules that govern this behavior but in practice he cannot notice the change in the behavior when he or someone else adds a new method to a base class in a later version of the code.

   Stay tuned for part 3 which will deal with exceptions.
Tags:   english programming 
Posted by:   Stilgar
01:29 06.07.2010

Comments:

First Previous 1 Next Last 

Posted by   JOKe (Unregistered)   on   15:13 06.07.2010

@Override can be made mendatory in eclipse... so .. who cares about the compiler :? :) ( p.s. eclipse uses its own compiler not java compiler for fast compiling on save and validating the code before compiling based on 23123412312213 rules that you can specify like what is optional what is not what is warning what is error etc )

Posted by   npavlov   on   15:23 06.07.2010

@JOKe,

We're comparing languages here, not compilers and IDEs.

Posted by   JOKe (Unregistered)   on   15:57 06.07.2010

you have to understand something... or 2 things.
First... noone cares about C#... is it better or no because it is own microsoft even if it is better no one cares.
Second... you are comparing the Runtime/VM or JIT many many times on the other posts which is not the language you are comparing some microsoft windows only not portable shit which runs only on windows and some phones wich doesnt exist and which noone buy with the most popular programming language more popular even than c and c++.

but its better to compare the language at least with some language which has a chance for the first place... like C .. common even VB is more used than C#... but this is a total joke I hope.


Anyway on the topic
second problem:
yep it is fixed with @Override
first problem: yes it is virtual by default and 99% of the java developers are not dumb and they know it is virtual by default.
So..
Case 1:
class Dog have a method talk()
i want CrazyDog have a method talk().
it is normal that the child of class Dog if it has a method talk it should be virtual there is no reason to not having virtual method the idea is that the crazyDog is speaking differently than the Dog so you will use a polymorphism in 100% of this case so .. in your noone uses it language you will write virtual on 99% of cases.(ou and override yes).I have never saw in 5 years unintended polymorphism NEVER it is intended in 100% of cases even if you dont understand it even if the CrazyDog author doesnt saw that there is a talk in the dog itself even if he doesnt want polymorphism there is nothing wrong to have polymorphism in this case EVEN if he doesnt know there are no problems.

Case 2 if the author of Dog changes the talk method then the polymorphism is gone... thats why you have @Override right ? (and CTRL+T shortcut in eclipse) which shows you all classes which are overriding this method, before changing its name. Yes there is no warning but as I said before because in 100% the polymorphism is intended than in 100% the polymorphism is used than in 100% you will see a compile error trying to call method on the Dog which doesnt exist.

About the performance maybe dont know anyway noone cares about C# performance I cannot test it on my Ubuntu or Sollaris or FreeBSD sorry :(
About your example... man I know that C# guys doesnt have any knowadge about how the things should be called and how to write nice code... and I know you have a lot of classes with name "A" and "B" and methods like "foo" but .. common use something manful... but as you can see if you use something meenful like Animal with abstract method talk, Dog with method talk and CrazyDog with method talk ... than the polymorphism will look right :)

Posted by   Stilgar   on   16:20 06.07.2010

The Eclipse option is cool. Too bad you need the IDE to fix the broken language design. You've never seen unintended polymorphism but obviously someone has seen it otherwise why add the @Override annotation? BTW you are aware that C# supports polymorphism right?

And if there is something in your post that no one cares about it is Ubuntu, Solaris and FreeBSD and not C#. What is more C# is 100% compatible with Mono which runs on the platforms no one cares about just fine. However OSs have nothing to do with good language design.

Posted by   JOKe (Unregistered)   on   16:28 06.07.2010

the performance of mono is so bad.... :)))
if you want to say that the C# performance is good because the language is created with performance in mind oki compare with mono :)
Anyway I will not speak about performance as I said there is no way to "compare it"

About override annotation it was created to makes some C# people happy they even change where the @Override can be applied between JDK 1.5 and JDK 1.6 and they didnt break anything maybe because no one use it :)
I know that C# supports polymorphism I am just saying that in 99% of C# cases you have to write virtual before methods.
Anyway lets explain how a project is made in real company.
Noone cares about compiler errors.
THere is a Xml file with checkstyles which are applied on the code on every save.
There is a xml file with findbugs which are also applied on the code.
there is a eclipse config with rules for formating, validation what can be writen what cannot for example the autoboxing/unboxing is disabled.

Then when you start writing .. you use this rules no one cares about @Overide.. if there is a rule saying @Override should be specified ALWAYS because somone has saw unintended polymorphism somewhere( never seen @Override as mendatory till now) then everyone will use it ... Btw there is a option in eclipse again if you want when the @Override is not specified if you are overriding a method to have a warning or error. Even before Java 1.5 if you  use old code you can say that in case of overriding there is a warning saying that you are doing overriding ( I checked it works ) so if you want and have it noone will override something without intention.

Posted by   Stilgar   on   16:49 06.07.2010

So they added the annotation to the most popular language in the Universe to make the C# people no one cares about happy?

I understand that the process with style checks and so on will be needed when you are using a language that sucks. I also understand that you can easily ignore the fact that the language sucks and produce software with it and this software will often be good. The PHP people are masters of this. I understand that in the Java world people are used with the sucky language and have many ways to work around the issues. Guess what! I DON'T CARE how you work around the issues. These are articles about language design and this is what I care about. You are free to go elsewhere and compare your language issue workarounds with the PHP people. There you will have a match because they too are into the "I don't see a problem therefore it does not exist and what is more my website works and Facebook uses PHP" mentality.

Posted by   JOKe (Unregistered)   on   18:01 06.07.2010

btw so this is for comparing a language which is a 15 years old with a language which is ? how 3 years old ? :) kidding oki 6 years old why you dont compare C# with something newer like Scala or Groovy for example ?
It will be the same if I explain how java is superior to C++ which is some years older.
I mean every new language has some nice ideas which doesnt exist on the old languages. I think this is true for every language ( except PHP which is even newer than Java but it sucks anyway ).
The reason why you are comparing with Java is because it is the most popular language ? or ?

Posted by   Stilgar   on   18:38 06.07.2010

As I pointed out in part 0 I am comparing with Java just because it is so easy. There are no ideological differences. You cannot really compare Java to C++ because they aim for different things. If you compare Java and C++ you first have to agree on whether automatic memory management is good thing, whether you should have complete control, etc. I even avoid (for now) pointing out features that Java is missing and just discuss stuff it implemented in non-optimal way.

I can hardly compare C# and Groovy because they are so different and the argument about the typing discipline is so religious that you cannot meaningfully compare anything. Scala is also quite different but closer to C# and I can assure you if we compare existing features in both languages C# will stand quite well if not on top. What is more I don't know enough Scala.

And finally if you read part 0 you will see that you are ALMOST right on the last one. I have yet to see a flamewar about Scala vs C# (in fact I am interested do you know any?) but I quite often take part in Java vs C# flamewars.

BTW according to Wikipedia Java appeared in 1995 and C# in 2001. This dates are probably based on first public release.

Posted by   ivelinka   on   19:03 06.07.2010

I agree with JOKe on "btw so this is for comparing a language which is a 15 years old with a language which is ? how 3 years old ? :) kidding oki 6 years old". I agree that C# as a language (not tools or frameworks where Java beats it in every way) is better. That's normal because the guys that work on C# took the best things out of Java and fixed the problems because they had an clear vision what's bad, they had an example before their eyes - Java. After all Java was out years before C# and many projects were written in Java. These features were implemented in that way long time ago when it seemed to be a good idea. The Java designers admit that. They say that it is important to keep backward compatibility, because there are many many many legacy projects written in Java out there (I guess not that many are written in C# because as far as I remember there were some changes in the language that weren't backward compatible, right?), that's why most of the problems cannot be fixed (although I believe that generics can be fixed without breaking legacy projects).

Posted by   npavlov   on   16:42 07.07.2010

@Ivelinka, the series are a comparison, so there is no need to find excuses here.  It is just the way it is.  There is nothing wrong in being criticized.  You can only learn your mistakes and try to come up with something better.  Sun / Oracle are obviously looking into making improvements, just like MS constantly does with C#.

Speaking of backwards compatibility, MS are very, very, very conscious about it.  Windows, starting 95, has always containing many hacks to make it possible for older popular programs to run, even when it is perfectly clear that the programs themselves are faulty (source: Old New Thing).  But sometimes you simply have to make sacrifices to allow yourself to go on.

Just an example: SQL Server (all versions since 7.0) can run databases in "legacy" modes, emulating completely the old version you ask it to run at, including all SQL dialect specifics and intricate internals.  But, it can also work in its latest and fullest release.

There always comes a point that if you need 100% compatibility, you need to stick with the old compiler.  For any language out there.

Posted by   Guest (Unregistered)   on   09:07 24.11.2010

A very one-sided article. There is nothing wrong with preferring C# to Java. But consequently presenting only arguments for the one and pretending the arguments for the other did not exist makes your otherwise informative article sound like promotional blah-blah. Instead, you should highlight both sides fairly and explain why you *personally* prefer the one to the other.

Posted by   Stilgar   on   11:45 24.11.2010

Frankly I don't know many arguments for Java from a language perspective. Can you provide some?

Posted by   Guest (Unregistered)   on   21:01 13.12.2010

See, reading articles and comments like this one just goes to show how people can become emotional about the computer language they work with.  We should all come to see that no one language is perfect, no one system is flawless.

So what if people cannot see that most of these tools including eclipse are helping drive the GDD aspects of open source and a million examples of bad code that is still looked at daily as samples and in some cases God forbid plastered right into a production grade system.

I have seen the ugly side of those platforms some would swear by, UBUTU and company, I used to run a Red Hat 5 box and also had a SCO Unix box along with other examples of useless junk I should never have had at home.

But hey this is the real world and real people are using these things to become rich and famous...

PHP now there is a demon all on his own along with his best friend MySql and Apache...  May I never see the inside of one of those config files ever again.

:)

Sorry this is more of a reaction to some of the negative comments I read as opposed to the actual face value of the thread, I do not know enough about Java and C# to make any educated comment.

First Previous 1 Next Last 


Post as:



Post a comment: