Concepts / Subroutine Signatures and Parameters

Subroutine Signatures and Parameters

The signature of a subroutine does not include its return type.

  • Programming

A Natural Guess About Overloading

Suppose you are writing a class with two subroutines that share the same name. This arrangement is called overloading. When a beginner first meets overloading, a natural guess is that the compiler should be able to tell the two versions apart by looking at everything about them. The name, the parameters, and the type of value the subroutine hands back all seem like reasonable clues.

This article examines the last of those clues, the return type, and shows why it cannot be used to tell overloaded subroutines apart. By the end, you should be able to look at a pair of declarations and decide whether the class can legally contain both.

Tracing Two Same-Named Declarations

Before reading any rule, look at two method declarations side by side. Both are named getValue, both take no parameters, and they differ only in the type of value they return. Read them carefully and keep the question in mind: does the class now contain two distinct subroutines, or has the second declaration conflicted with the first?

java
Notes on the code
  • First declaration: name getValue, no parameters, returns int
  • Second declaration: same name, same empty parameter list, returns double
getValuenamegetValuenameno parametersparameter listno parametersparameter listintreturn typedoublereturn typesame namesame parameters
What does the compiler compare between these two declarations, and why does it reject the second one?

Notice what matches and what differs. The name matches, and the parameter list matches (both are empty). The only difference is the return type, int versus double. Those are the two declarations the rest of this article asks you to judge.

What a Signature Contains

Definition

The signature of a subroutine does not include its return type. A subroutine's signature is made up of its name and its parameters, and it is the signature that distinguishes one subroutine from another within a class.

intreturn type, outside thesignaturegetValuename, part of the signature(String prompt)parameter types, part ofthe signature
Which parts of a method declaration make up its signature, and which part sits outside it?

Reading the diagram from left to right: the return type int is the part that sits outside the signature. The name getValue and the parameter list (String prompt) form the signature. Because the return type is excluded, two declarations that agree on name and parameters have the same signature, even if their return types differ.

Why the Compiler Rejects the Pair

Overloading means giving several subroutines in the same class the same name and relying on the differences in their signatures to tell them apart. Since the signature does not include the return type, the only things that can make two same-named subroutines distinct are the things the signature does contain.

Apply that to the getValue pair from earlier. Both declarations have the name getValue and the empty parameter list, so their signatures are identical. The only difference is the return type, and the return type is not part of the signature. The class therefore has nothing to distinguish one getValue from the other, and the arrangement is a syntax error.

The rule is not a restriction against having two methods with the same name. Overloads are allowed as long as their signatures differ. A second method with the same name becomes legal once it has a different parameter list, or once it uses a different name entirely.

Predicting Which Pairs Can Coexist

java
Notes on the code
  • read() returning int and read(String) returning int: the parameter lists differ, so the signatures differ
  • read() returning double: same name and empty parameter list as the first read(), differing only in return type

Work through the three declarations using only the signature. The pair read() and read(String prompt) can coexist, because their parameter lists differ. The third declaration, another read() with a double return type, cannot coexist with the first read(), because its signature matches the first exactly and only the return type differs. The class is rejected on the third declaration, not the second.

How TextIO Names Its Input Routines

The TextIO class is a useful illustration of this rule in action. A programmer might expect its input routines for reading different types of values to share one name, such as getln, with the return type telling the caller what kind of value came back. The rule forbids that design, so TextIO does not use it.

In a given class, there can only be one routine named getln that takes no parameters. If getln() returned an int in one version and a double in another, those two versions would have identical signatures and would be a syntax error. The input routines are therefore distinguished by having different names, such as getlnInt() and getlnDouble().

DesignCan the class legally contain it?Why
getln() returning int, plus getln() returning doubleNoSame name and empty parameter list; only the return type differs
getlnInt() and getlnDouble()YesDifferent names, so the signatures differ

Two ways to provide input routines for different value types

Mistakes When Reasoning About Return Types

  • Common mistake

    Assuming the return type helps the compiler tell overloads apart

    What it looks like

    Writing getValue() returning int and getValue() returning double in the same class and expecting the caller's assignment to choose the right one

    Why it fails

    The return type is not part of the signature, so the compiler has no basis to distinguish the two declarations

    Do this instead

    Give the overloads different parameter lists or different names

  • Common mistake

    Thinking a same-named method is always illegal

    What it looks like

    Writing read() and read(String prompt) and concluding the class is invalid

    Why it fails

    Overloads are allowed when their signatures differ, and a different parameter list makes the signatures differ

    Do this instead

    Check the parameter list, not just the name, before deciding whether a pair is legal

  • Common mistake

    Treating getln() and getInt() as variants that differ only by return type, so they should be the same method

    Why it fails

    Different names give different signatures, which is exactly how TextIO separates its input routines

    Do this instead

    Use distinct names for routines whose only difference is the type of value they produce

Checking Your Understanding

What do you think happens?

Two methods in the same class are both named square and both take one int parameter. One returns int and the other returns double. Can both be declared?

  • Yes, because the return types are different

  • No, because the signatures are identical

Reveal answer
Answer:

No, because the signatures are identical

The signature is made of the name and parameter types. Both methods have name square and one int parameter, so the signatures match. The return type is not part of the signature, so the pair is a syntax error.

MEDIUM

Using only the signature, decide whether each pair can coexist in one class. Pair A: process(int x) returning int and process(double x) returning int. Pair B: process(int x) returning int and process(int x) returning double. Explain your reasoning in terms of name and parameter types.

Hints
  • Pair A differs in the type of its parameter, which is part of the signature
  • Pair B has identical names and parameter types, and differs only in return type

Key Takeaways

  • A subroutine's signature is made of its name and parameters; the return type is not part of it.
  • Two subroutines in the same class with the same signature but different return types is a syntax error.
  • Overloads must be distinguished by different parameters or different names.
  • TextIO uses getlnInt() and getlnDouble() rather than a single getln() name, because a single getln() cannot be reused with different return types.