Doing practise questions for a Java exam which have no answers (useful) I have been asked to do the following:
Write a class called Person
with the following features:
- a
private int
calledage
; - a
private String
calledname
; - a constructor with a
String
argument, which initialisesname
to the received value andage
to0
; - a public method
toString(boolean full)
. Iffull
istrue
, then the method returns a string consisting of the person’s name followed by their age in brackets; iffull
isfalse
, the method returns a string consisting of just the name. For example, a returned string could beSue (21)
orSue
; - a public method
incrementAge()
, which increments age and returns the new age; - a public method
canVote()
which returnstrue
ifage
is18
or more andfalse
otherwise.
My code is as follows can someone point out any errors?
public class Person
{
private int age;
private String name;
public Person(String st)
{
name = st;
age = 0;
}
public String toString(boolean full)
{
if(full == true)
{
return name + "(" + age + ")";
}
else
{
return name;
}
}
public int incrementAge()
{
age++;
return age;
}
public boolean canVote()
{
if(age >= 18)
{
return true;
}
else
{
return false;
}
}
}
-
\$\begingroup\$ I don't see any errors :) \$\endgroup\$Cata– Cata2011年05月30日 14:27:22 +00:00Commented May 30, 2011 at 14:27
14 Answers 14
instead of
if(full == true)
use
if (full)
and instead of
if(age >= 18)
{
return true;
}
else
{
return false;
}
use:
return age >= 18
-
\$\begingroup\$ Thank you both for your answers, just wee small minor things i need to keep an eye on then. \$\endgroup\$user445714– user4457142011年05月30日 14:31:38 +00:00Commented May 30, 2011 at 14:31
return name + "(" + age + ")";
to
return name + " (" + age + ")";
That's fine, but I would have written the last method as return (age >= 18);
I don't think it's a good idea to write toString
method with arguments - doing so you will not override the default Object.toString
and will have no benefits from using it outside your code. For example, when outputting elements of a collection which contain Person
won't display neither age nor name, but something like Person@a3f33f
(default implementation).
At least provide toString
with no arguments as well
-
\$\begingroup\$ Denisk that actually moves onto my next question, Does the Person class overload or override any methods? Briefly explain your answer. \$\endgroup\$user445714– user4457142011年05月30日 14:34:20 +00:00Commented May 30, 2011 at 14:34
-
\$\begingroup\$ I was going with override until i seen your comment and would go with overload the Object.toString? \$\endgroup\$user445714– user4457142011年05月30日 14:35:08 +00:00Commented May 30, 2011 at 14:35
-
\$\begingroup\$ Currently you have
toString
method overloaded - thus, you actually have 2toString
methods - one inherited fromObject
(default no-arg method), and one withboolean
argument. If you declared yourtoString
with no arguments it would overrideObject.toString
, and you would end up with 1toString
method (which, as I have mentioned, can be widely used by many things outside your own code) \$\endgroup\$denisk– denisk2011年05月30日 14:38:55 +00:00Commented May 30, 2011 at 14:38 -
\$\begingroup\$ I agree with denisk, and want to point out that flags like
full
in method arguments are a code smell: A method should do one and only one thing (Single Responsibility Principle), and a method with a flag does at least two things. Uncle Bob agrees as well (Clean Code: amazon.de/Clean-Code-Handbook-Software-Craftsmanship/dp/… ) \$\endgroup\$Landei– Landei2012年03月03日 13:44:08 +00:00Commented Mar 3, 2012 at 13:44 -
\$\begingroup\$ The
toString(boolean)
method is part of the assignment requirements. But normally, this is good advice. \$\endgroup\$Eva– Eva2013年01月16日 12:04:32 +00:00Commented Jan 16, 2013 at 12:04
Your code is almost fine. I would change two things:
The following is a little shorter :)
public boolean canVote()
{
return age >= 18;
}
Your toString(true)
would return "Sue(21)"
rather than the "Sue (21)"
(with space) which is asked for. My toString would look like this:
public String toString(boolean full)
{
String str = name;
if(full) {
str += " (" + age + ")";
}
return str;
}
If the age is implemented as a primitive integer there is no need to initialize it to 0 because all primitive number instance variables are initialized to 0 by default. Anyway if you had used a wrapper instead (Integer) the initialization to 0 is required.
Take a look at the "Default Values" section:
http://download.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
In addition to the other comments, on your constructor, having an argument called "st" isn't particularly useful to the reader as it doesn't tell them what it's for. From a code style perspective might be better to have an argument called name, and explicitly set this.name = name
in the body.
-
1\$\begingroup\$ To add on, at this moment of learning it may seem not to matter, but when you're developing, these little things that make the usage more intuitive (especially when you're using auto-completion) will reduce your (and others') pain. \$\endgroup\$blizpasta– blizpasta2011年05月30日 14:44:06 +00:00Commented May 30, 2011 at 14:44
How about adding a constant for 18, say MIN_AGE_TO_VOTE?
And:
return name + (full ? " (" + age + ")" : "");
Less readable, I agree :-)
-
1\$\begingroup\$ +1 for only the constant. (I agree, the ternary operator is not too readable and harder to maintain.) \$\endgroup\$palacsint– palacsint2012年07月07日 15:56:51 +00:00Commented Jul 7, 2012 at 15:56
Use String.format
instead of string concatenation:
(削除) return name + "(" + age + ")"; (削除ここまで) becomes
return String.format("%s (%s)", name, age);
-
\$\begingroup\$ It's a Java question ;) \$\endgroup\$palacsint– palacsint2012年07月07日 22:09:20 +00:00Commented Jul 7, 2012 at 22:09
The name field could be
final
. Making a variable final relieves the programmer of excess mental juggling - he/she doesn't have to scan through the code to see if the variable has changed. (From @nerdytenor's answers.)You should check the argument in the constructor. Does it make sense to create a
Person
object with a name which isnull
or an empty String? If not, check it and throw aNullPointerException
or anIllegalArgumentException
. (Effective Java, Second Edition, Item 38: Check parameters for validity)A note about the specification:
Flag arguments are ugly. Passing a boolean into a function is a truly terrible practice. It immediately complicates the signature of the method, loudly proclaiming that this function does more than one thing. It does one thing if the flag is true and another if the flag is false!
Source: Clean Code by Robert C. Martin, Chapter 3: Functions.
This should be two methods:
toString()
andtoFullString()
, for example, without any parameter.
Looks fine, only canVote is maybe a bit clumsy:
public boolean canVote()
{
return age >= 18;
}
I would see if you can make the code less verbose.
public boolean canVote() {
return age >= 18;
}
This is also less verbose
public int incrementAge() {
return ++age;
}
-
\$\begingroup\$ I worry that a student might be docked points for readability if they put that answer. Otherwise, I would write it like that too. \$\endgroup\$Eva– Eva2013年01月16日 12:07:13 +00:00Commented Jan 16, 2013 at 12:07
public Person(String st)
{
name = st;
age = 0;
}
st
is not a good name for a variable or parameter, because it does not tell you what it contains. It implies that it means "string", but even that is not clear. Call it name
instead. Use this.name = name
to distinguish member and parameter names.
Put the opening brackets on the first line of the block, not at the beginning of the next line, since it is common practise in Java (even though I find it prettier if it is on the next line, since I code C# more than Java). Other Java developers reading your code will be used to it.
Others have already pointed it out: Write if (full)
instead of if (full == true)
. That is clearer and easier to read. You can use the ternary operator for a one liner:
return full ? name + "(" + age + ")" : name;
.
Your incrementAge()
looks fine.
public boolean canVote()
{
if(age >= 18)
{
return true;
}
else
{
return false;
}
}
Your indentation is weird. Use 4 spaces (less common tabs with width of 4 spaces) for indentation. You have sometimes 3 spaces, sometimes 2.
Since age >= 18
is a boolean expression, you can return the result just like this:
return age >= 18;
Use spaces after if
and for
(also while
and similar) keywords. That makes the code clearer and more readable:
if (someCondition) {
doThis();
}