Inheritance
Conceptually, inheritance in C# works mostly the same as in Java: subclasses that override methods in the superclass, etc. Below, we highlight the small differences between the two languages.
Inheritance Syntax
Java opted to use a relatively verbose syntax to specify superclasses and interface implementations:
// Java
class Foo extends Bar implements Baz
{
}
C# preferred to keep it short:
// C#
class Foo : Bar, IBaz
{
}
Note that the superclass has to come first, followed by the interfaces.
Superconstructor
In Java, the superclass’s constructor is called as follows:
// Java
class Foo extends Bar
{
public Foo()
{
super();
}
}
Here, super()
must come first in the constructor’s body, which makes sense:
the subclass “builds on top” of the superclass, meaning that the foundations
have to be build before being able to add something on top of it.
C# enforces this rule by using syntax that gives the programmer no choice but to put the call to the superconstructor first:
// C#
class Foo : Bar
{
public Foo() : base()
{
}
}
C# uses slightly different terminology: the superclass is called the base class,
hence the keyword base
.
Virtual
In Java, every method is overrideable by default. C# does not agree with this
choice: according to its designers, making a method overrideable
should be a well thought out decision. For this reason,
methods in C# are not overrideable by default, except if you
explicitly make them so by adding the virtual
keyword. This way
you can clearly distinguish between methods that form the core
structure of the class and those that are meant
to be customized in subclasses.
public class Foo
{
public void NonoverrideableMethod() { ... }
public virtual void OverrideableMethod() { ... }
}
Override
Java 1.5 introduced annotations which allow programmers
to “annotate” parts of their code. For example,
it is possible to define an @author
annotation
that you can add to classes to indicate who wrote it.
This is not a particularly useful application:
the version control system is probably a much better choice
to keep track of who wrote what.
An annotation that comes predefined with Java 1.5
is @Override
. When attached to a method,
it expresses it is intended to override one of the superclass’s methods.
// Java
public class Foo
{
public void bar() { ... }
public void qux() { ... }
}
public class extends Foo
{
@Override
public void bar() { ... }
@Override
public void quks() { ... }
}
Thanks to the @Override
annotation, the compiler can
see that something’s wrong with quks
and will give
you an error message. Without @Override
, the compiler
would simply assume you meant to define an extra method, unrelated
to qux
. While optional in Java, making use of @Override
is
highly recommended as it lets the compiler catch more bugs.
Java could not make @Override
mandatory lest all existing code be broken.
However, C# has the luxury of making it mandatory since
this feature has been present since C#’s inception.
// C#
public class Foo
{
public virtual void bar() { ... }
public virtual void qux() { ... }
}
public class : Foo
{
public override void bar() { ... }
public override void quks() { ... }
}
Exercises
Exercises can be found on the master
branch.
exercises/inheritance/LoggerExercise