Inheritance syntax | CodeGuru

Inheritance syntax

Bruce Eckel’s Thinking in Java Contents | Prev | Next Inheritance is such an integral part of Java (and OOP languages in general) that it was introduced in Chapter 1 and has been used occasionally in chapters before this one because certain situations required it. In addition, you’re always doing inheritance when you create a […]

Written By
CodeGuru Staff
CodeGuru Staff
Mar 1, 2001
5 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

Inheritance


is such an integral part of Java (and OOP languages in general) that it was


introduced in Chapter 1 and has been used occasionally in chapters before this


one because certain situations required it. In addition, you’re always


doing inheritance when you create a class, because if you don’t say


otherwise you inherit from Java’s standard root class


Object

.

The


syntax for composition is obvious, but to perform inheritance there’s a


distinctly different form. When you inherit, you say “This new class is


like that old class.” You state this in code by giving the name of the


class as usual, but before the opening brace of the class body, put the

keyword
extends
followed by the name of the
base
class
.
When you do this, you automatically get all the data members and methods in the
base class. Here’s an example:
//: Detergent.java
// Inheritance syntax & properties
 
class Cleanser {
  private String s = new String("Cleanser");
  public void append(String a) { s += a; }
  public void dilute() { append(" dilute()"); }
  public void apply() { append(" apply()"); }
  public void scrub() { append(" scrub()"); }
  public void print() { System.out.println(s); }
  public static void main(String[] args) {
    Cleanser x = new Cleanser();
    x.dilute(); x.apply(); x.scrub();
    x.print();
  }
}
 
public class Detergent extends Cleanser {
  // Change a method:
  public void scrub() {
    append(" Detergent.scrub()");
    super.scrub(); // Call base-class version
  }
  // Add methods to the interface:
  public void foam() { append(" foam()"); }
  // Test the new class:
  public static void main(String[] args) {
    Detergent x = new Detergent();
    x.dilute();
    x.apply();
    x.scrub();
    x.foam();
    x.print();
    System.out.println("Testing base class:");
    Cleanser.main(args);
  }
} ///:~ 

This


demonstrates a number of features. First, in the


Cleanser
append( )

method,


String

s


are concatenated to


s

using the


+=

operator, which is one of the operators (along with ‘


+

’)


that the Java designers “overloaded” to work with

Strings.

Second,


both


Cleanser

and


Detergent

contain a

main( )
method. You can create a
main( )
for each one of your classes, and it’s often recommended to code this way
so that your test code is wrapped in with the class. Even if you have a lot of
classes in a program only the
main( )
for the
public
class invoked on the command line will be called. (And you can have only one
public
class per file.) So in this case, when you say
java
Detergent
,
Detergent.main( )
will be called. But you can also say
java
Cleanser
to
invoke
Cleanser.main( ),
even though
Cleanser
is not a
public
class. This technique of putting a
main( )
in each class allows easy
unit
testing for each class. And you don’t need to remove the
main( )
when you’re finished testing; you can leave it in for later testing.

Here,


you can see that


Detergent.main( )

calls


Cleanser.main( )

explicitly.

It’s


important that all of the methods in


Cleanser

are


public

.


Remember that if you leave off any access specifier the member defaults to


“friendly,” which allows access only to package members. Thus,


within this package, anyone could use those methods if there were no access


specifier.


Detergent

would have no trouble, for example. However, if a class from some other package


were to inherit


Cleanser

it could access only


public

members.


So to plan for inheritance, as a general rule make all fields


private

and


all methods


public.

(

protected

members


also allow access by derived classes; you’ll learn about this later.) Of


course, in particular cases you must make adjustments, but this is a useful


guideline.

Note


that


Cleanser

has a set of methods in its interface:


append( )

,


dilute( )

,


apply( )

,


scrub( )

and


print( )

.


Because


Detergent

is


derived
from

Cleanser

(via the

extends
keyword) it automatically gets all these methods in its interface, even though
you don’t see them all explicitly defined in
Detergent.
You can think of inheritance, then, as
reusing
the interface.

(The implementation comes along for free, but that part isn’t the primary
point.)

As


seen in


scrub( )

,


it’s possible to take a method that’s been defined in the base


class and modify it. In this case, you might want to call the method from the


base class inside the new version. But inside


scrub( )

you cannot simply call


scrub( )

,


since that would produce a recursive call, which isn’t what you want. To


solve this problem Java has the

keyword
super
that refers to the “
superclass”
that the current class has been inherited from. Thus the expression
super.scrub( )
calls the base-class version of the method
scrub( ).

When


inheriting you’re not restricted to using the methods of the base class.


You can also add new methods to the derived class exactly the way you put any


method in a class: just define it. The


extends

keyword


suggests that you are going to add new methods to the base-class interface, and


the method


foam( )

is an example of this.

In


Detergent.main( )

you


can see that for a


Detergent

object you can call all the methods that are available in


Cleanser

as well as in


Detergent

(i.e.


foam( ))

.

Initializing
the base class

Since


there are now two classes involved – the base class and the

derived
class – instead of just one, it can be a bit confusing to try to imagine
the resulting object produced by a derived class. From the outside, it looks
like the new class has the same interface as the base class and maybe some
additional methods and fields. But inheritance doesn’t just copy the
interface of the base class. When you create an object of the derived class, it
contains within it a
subobject
of the base class. This
subobject
is the same as if you had created an object of the base class by itself.
It’s just that, from the outside, the subobject of the base class is
wrapped within the derived-class object.

Of


course, it’s essential that the base-class subobject be initialized


correctly and there’s only one way to guarantee that: perform the


initialization in the constructor, by calling the base-class constructor, which


has all the appropriate knowledge and privileges to perform the base-class


initialization. Java automatically inserts calls to the base-class constructor


in the derived-class constructor. The following example shows this working with


three levels of inheritance:

//: Cartoon.java
// Constructor calls during inheritance
 
class Art {
  Art() {
    System.out.println("Art constructor");
  }
}
 
class Drawing extends Art {
  Drawing() {
    System.out.println("Drawing constructor");
  }
}
 
public class Cartoon extends Drawing {
  Cartoon() {
    System.out.println("Cartoon constructor");
  }
  public static void main(String[] args) {
    Cartoon x = new Cartoon();
  }
} ///:~ 

The


output for this program shows the automatic calls:

Art constructor
Drawing constructor
Cartoon constructor

You


can see that the construction happens from the base “outward,” so


the base class is initialized before the derived-class constructors can access


it.

Even


if you don’t create a constructor for


Cartoon( )

,


the compiler will

synthesize
a default constructor for you that calls the base class constructor.


Constructors
with arguments

The


above example has default

constructors;
that is, they don’t have any arguments. It’s easy for the compiler
to call these because there’s no question about what arguments to pass.
If your class doesn’t have default arguments or if you want to call a
base-class constructor that has an argument you must explicitly write the calls
to the base-class constructor using the
super
keyword and the appropriate argument list:
//: Chess.java
// Inheritance, constructors and arguments
 
class Game {
  Game(int i) {
    System.out.println("Game constructor");
  }
}
 
class BoardGame extends Game {
  BoardGame(int i) {
    super(i);
    System.out.println("BoardGame constructor");
  }
}
 
public class Chess extends BoardGame {
  Chess() {
    super(11);
    System.out.println("Chess constructor");
  }
  public static void main(String[] args) {
    Chess x = new Chess();
  }
} ///:~ 

If


you don’t call the base-class constructor in


BoardGame( )

,


the compiler will complain that it can’t find a constructor of the form


Game( )

.


In addition, the call to the base-class constructor


must

be the first thing you do in the derived-class constructor. (The compiler will


remind you if you get it wrong.)


Catching
base constructor exceptions

As


just noted, the compiler forces you to place the base-class constructor call


first in the body of the derived-class constructor. This means nothing else can


appear before it. As you’ll see in Chapter 9, this also prevents a


derived-class constructor from catching any exceptions that come from a base


class. This can be inconvenient at times.


Contents

|

Prev

|

Next
CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.