Subroutine Signatures and Parameters
The signature of a subroutine does not include its return type.
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?
- First declaration: name
getValue, no parameters, returns int - Second declaration: same name, same empty parameter list, returns double
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
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.
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
read()returning int andread(String)returning int: the parameter lists differ, so the signatures differread()returning double: same name and empty parameter list as the firstread(), 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().
| Design | Can the class legally contain it? | Why |
|---|---|---|
| getln() returning int, plus getln() returning double | No | Same name and empty parameter list; only the return type differs |
| getlnInt() and getlnDouble() | Yes | Different 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 likeWriting getValue() returning int and getValue() returning double in the same class and expecting the caller's assignment to choose the right one
Why it failsThe return type is not part of the signature, so the compiler has no basis to distinguish the two declarations
Do this insteadGive the overloads different parameter lists or different names
Common mistake Thinking a same-named method is always illegal
What it looks likeWriting read() and read(String prompt) and concluding the class is invalid
Why it failsOverloads are allowed when their signatures differ, and a different parameter list makes the signatures differ
Do this insteadCheck 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 failsDifferent names give different signatures, which is exactly how TextIO separates its input routines
Do this insteadUse 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?
Reveal 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.
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()andgetlnDouble()rather than a singlegetln()name, because a singlegetln()cannot be reused with different return types.