Reputation: 598
I am currently taking an Android class and when I got the first assignment grade, I lost points due to using an empty constructor rather than using one with fields. The professor said using fields is better. Is he correct? If so, why?
Is this better?
Photos pic = new Photos(path, title, author, date);
public Photos(String url_path, String title, String author,
String date_taken) {
super();
this.url_path = url_path;
this.title = title;
this.author = author;
this.date_taken = date_taken;
}
Or this? Or does it matter?
Photos pic = new Photos();
pic.setUrl_path(path);
pic.setTitle(title);
pic.setAuthor(author);
pic.setDate_taken(date);
public Photos() {
super();
}
Upvotes: 4
Views: 195
Reputation: 48634
In general, you should prefer a constructor that is given initial values, to setting those values later using setter methods. But why?
It is possible to just think of an object as a bag for holding a jumbled collection of fields, which in theory could have any value, including invalid values. In that case, using a no-args constructor followed by a setter would be OK.
But it transpired (in the 1970s) that programming in that way caused difficulties when creating large or complicated programs.
Imagine you had a Person
class that had an attribute that recorded the name of the person, as a String
, and the nature of your program was that you will, and must, always know the name of a person. As you must always have the name, it must never be null
. If you have a no-args constructor, what value would it initialise the name to? It is not permitted to leave the name as null. But it makes no sense to set the name to an arbitrary default name, because there is no generally useful default for the name of a person. So, if you want to impose the constraint that a Person
object always has a (non null
) name, your constructor must have an argument that tells it what the name of the new Person
object will be.
It is useful to think of an object, not as a jumble of values, but as values that have constraints on them. It is very helpful if the code for that object is written in a way that makes it impossible to breach those constraints. Then, any code that uses that object can safely assume those constraints will be met, even if you do not know (or remember) what the other parts of the code do. This enables you to concentrate on one bit of the code at once, without having to examine elsewhere to check whether an important constraint will be met. In most cases, only constructors given initial values can construct an object that meets all the constraints.
Upvotes: 1
Reputation: 19700
As pointed out by Dmitry Bychenko in the comments, parameters are passed via the constructor, When the construction
of an object
depends upon those mandatory parameters.
The other parameters are generally set once the object has been constructed.
Take the example of the constructor of the File
class,
File f = new File("filepath");
Here filepath
is a parameter without which a File
object cannot be constructed, since it needs to refer to a location where the file resides. And its attributes such as readable
, can be set through the setters, and come into picture only after the file reference has been constructed successfully.
f.setReadable(arg0)
Since in your example, the Photo
class doesn't depend upon any of its parameter values for its construction, a parameterized
constructor is not necessary.
Upvotes: 2
Reputation: 1042
If your object Photo (in this case) always has those attributes to be a valid photo I believe you should include the assignment of those attributes in your constructor. (path, title, author, date);
And since your are making one photo object. The name of the constructor and class should be Photo (not Photos)
public Photo(String urlPath, String title, String author,
String dateTaken) {
super();
this.urlPath= urlPath;
this.title = title;
this.author = author;
this.dateTaken= dateTaken;
}
Some more comments:
You only need to call super() if the Photo class is a derived class. Use camel casing for your argument names and try to be consistent.
Upvotes: 1
Reputation: 837
Another aspect of consideration is how you want to wire together classes. If you are using dependency injection container like spring or guice, a empty constructor with setters and getters allows you to wire references from and to your object.
I prefer to separate object construction from execution, so as long as your code is factored in that way it would be modular, extensible and clean.
Upvotes: 1
Reputation: 6816
When you use setter the objects are mutable and their state can be manipulated but anyone who has access to it.
The other approach makes the objects in a single defined state and are typically read-only once they are created as they cannot be modified from outside the class. How ever they can always be mutated inside the class.
Example:
public class Setters {
private int value;
public void setValue(int val) {
value=val;
}
public int getValue() {
return value;
}
}
public void function(Setter setter){
setter.setValue(20);
}
// In main
Setter setter = new Setter();
setter.setValue(10);
function(setter);
System.out.println(setter.getValue());
In this case it will print 20 cause it is mutable
public class Setters {
private int value;
public setter(int val) {
value=val;
}
public int getValue() {
return value;
}
}
// In main
Setter setter = new Setter(10);
Setter setter1 = new Setter(20);
System.out.println(setter.getValue());
System.out.println(setter1.getValue());
This will print 10 and 20 you don't have a setter so these object will become read only after creation.
Upvotes: 2
Reputation: 597
Depends what class you are writing. If it is for Immutable objects it means you are not to provide accessors / mutators for it. In that case its necessary that you provide initial values for attributes at time of creation of object. Natural choice would be to pass them in constructor.
In your case of Photos, the attributes like Title, Date_Taken and Author are not supposed to be changed or can't be null and are supposed to be associated with "Photos" right from the creation, so it is better practice to provide arguments in constructor. Although you can provide getter/setter for URL since its value can change with time.
Upvotes: 1
Reputation: 218808
Neither is "better", they simply do different things. Which one is subjectively "better" depends on what you want to achieve with that class. Consider this code for example:
Photos pic = new Photos();
pic.setUrl_path(path);
pic.setTitle(title);
pic.setAuthor(author);
pic.setDate_taken(date);
Immediately following that first line, is the pic
object in a valid state? Does having no values set result in a meaningfully and contextually complete Photos
object? If the answer is "no" and if the fields being set are necessary in order to have a valid Photos
object, then they should be required by the constructor.
That is, the job of the constructor is to ensure that only a valid instance is created. Never assume that consuming code will follow up with setters, it might not. The job of ensuring valid state of the object is a responsibility that should be encapsulated within the object.
On the other hand, if a parameterless constructor can create a valid instance of Photos
then it's perfectly acceptable to have a parameterless constructor. You can have both, so consuming code has the option of which to use depending on the state is wishes to create:
public Photos() {
// set default values
}
public Photos(String url_path, String title, String author, String date_taken) {
// set supplied values
}
It all depends on what a valid state of a Photos
object can be and what is required (or not required) in order to achieve that state.
Upvotes: 4
Reputation: 620
In terms of efficiency, yeah, it is.
You could do it like this...
JButton b = new JButton();
b.setText("Hello everybody 1");
b.setIcon(b1);
JButton c = new JButton();
c.setText("Hello everybody 2");
c.setIcon(c2);
JButton d = new JButton();
d.setText("Hello everybody 3");
d.setIcon(d3);
JButton e = new JButton();
e.setText("Hello everybody 4");
e.setIcon(e4);
Or you could do
JButton b = new JButton("Hello everybody 1", b1);
JButton c = new JButton("Hello everybody 2", c2);
JButton d = new JButton("Hello everybody 3", d3);
JButton e = new JButton("Hello everybody 4", e4);
Far more streamlined, yes? Not to mention that things like variables, of which most classes have several, can be given default values from the getgo, instead of having to give them passive values when you are not even going to use those variables anywhere in your program.
Upvotes: 1