I am not sure if a similar question has been asked before, searched for it, but did not get any helpful answers.
As the question suggests, what is better, having an overloaded constructor or having multiple setter functions?
Scenario:
public class Something {
private int a;
private int b;
public Something(int a, int b) {
this.a = a;
this.b = b;
}
... // Do Something
}
Now, my basic requirement was for to have two parameters only. Now tomorrow, the requirement is changed and I am asked to add a new parameter, c and then the next day d, and given a statement saying we can have more fields.
I already have dependency for this constructor in multiple projects. Now, back to my question
Is it advisable to keep adding the new fields to the already overloaded constructor?
Create a new overloaded constructor every time I need to add a new field so that I don't break dependent code?
Or simply use the default empty default constructor and use setters only (messing up my immutability, which is not of high concern)
What is the advice that you can give me?
The most pleasant way to do this is to continue adding the fields to your constructor -- having setters means you can't have immutable objects, and immutable objects are always nice -- but possibly to investigate the builder pattern, which can help you limit yourself to just one constructor that gets called and "filled in" by the builder object.
The good thing about a constructor, as opposed to setters, is that it allows you to enforce the setting of required properties for an instance, rather than having the object be in a bad state until its correct setters are called. Also, as the other posters mentioned, immutability can be a very good thing, particularly in a multi-threaded context.
Nevertheless, your instincts are correct: constructors can grow unwieldy. To second the other posters yet again, the builder pattern can give you the best of both worlds in this situation. If you don't want the builder to be a nested class of the product, as it is depicted in the Java example in the Wikipedia article, then just put it in the same package as the product, and give the product package-protected setters. Also, you can add logic to enforce the setting of mandatory properties when the caller declares building to be complete.
The objective of having different constructors is to increase the reusability of the class. I think it will be more helpful to have a few different constructors that serve to your needs rather than having a lot of setters.
Also the constructors are more specific and improve the readability of your class and the api.
Do your other projects that depend on 2-arg constructor benefit in any way from new parameters? Do 2-arg constructors make sense with your new requirements?
Maybe you need to create another class, e.g. SomethingEx(Something) which would carry additional fields and have different constructors, but would share useful methods.
If useful methods to share are few and very short, it may be better to create an entirely different class, just to have fewer dependencies.
Related
This question already has answers here:
Why are getter and setter method important in java? [duplicate]
(6 answers)
Closed 7 years ago.
Encapsulation is hiding the data. I would like to hear some really interesting answers here.
What is the point behind keeping variables as private when we already declare public setter methods for variables?
I understand the usage of encapsulation but when we are making the setters as public what is the point behind keeping the variables as private, we can directly use public access modifiers.
Is it because we do not want others to know the exact way we are storing data or managing data on the back-end?
Is it because we do not want others to know the exact way we are
storing data or managing data on the back-end?
Yes, that's the point. It is related to the concepts of abstraction and information hiding too.
You provide a public setter that when invoked by the class client will have the effect that you have documented. It is none of the client's business how this effect is actually achieved. Are you modifying one of the class attributes? Ok, let the client know that, but not the fact that you are actually modifying a variable. In the future, you could want to modify your class so that instead of a simple backup variable it uses something completely different (a dictionary of attributes? An external service? Whatever!) and the client will not break.
So your setter is an abstraction that you provide to the client for "modify this class attribute". At the same time you are hiding the fact that you are using an internal variable because the client doesn't need to know that fact.
(Note: here I'm using the word "attribute" as a generic concept, not related to any concrete programming language)
I fully agree with Konamiman's answer, but I'd like to add one thing:
There are cases where you really don't want that abstraction. And that's fine.
A simple example I like to use here is a class for a 3-dimensional float vector:
class Vector3f {
public:
float x;
float y;
float z;
};
Could you make those fields private and provide setters instead? Sure, you could. But here you might argue that the class is really just supposed to provide a tuple of floats and you don't want any additional functionality. Thus adding setters would only complicate the class and you'd rather leave the fields public.
Now, you can easily construct scenarios where that might bite you later on. For instance, you might one day get a requirement that Vector3fs are not allowed to store NaNs and should throw an exception if anyone tries to do so. But such a hypothetical future problem should not be enough to justify introducing additional abstractions.
It's your call as a programmer to decide which abstractions make sense for the problem at hand and which ones would only get in your way of getting the job done. Unnecessary abstractions are over-engineering and will hurt your productivity just as much as not abstracting enough.
Bottom line: Don't blindly use setters everywhere just because someone claimed that's good practice. Instead, think about the problem at hand and consider the tradeoffs.
Because by encapsulation we provide single point of access. Suppose you define a variable and its setter as follows
String username;
public void setUsername(String username){
this.username = username;
}
Later you like to add some validation before setting username property. If you are setting the username at 10 places by directly accessing the property then you don't have single point of access and you need to make this change at 10 places. But if you have one setter method then by making a change at one place you can easily achieve the result.
Think about this : I'm representing a real life object, a Lion through a class. I'd do something like this.
class Lion {
public int legs;
}
Now my class is needed by some other developer to create an object and set its legs field. He'd do something like this
Lion jungleKing = new Lion();
jungleKing.legs = 15;
Now the question is, Java won't restrict him to setting any number more than 4 as the number of legs for that object. It's not an error, and it'll run just fine. But it's a logical blunder, and the compiler won't help you there. This way a Lion may have any number of legs.
But if we write the code this way
class Lion {
private int legs;
public void setLegs(int legs){
if(legs > 4){
this.legs = 4;
}
else this.legs = legs;
}
}
Now you won't have any Lion with more than 4 legs because the policy of updating the fields of the class has been defined by the class itself and there's no way anyone not knowing the policy is going to update the legs field because the only way to update the legs field is through the setLegs() method and that method knows the policy of the class.
Although Konamiman's answer is spot on, I'd like to add that, in the particular case of public setters versus directly exposing public fields you are asking, there is another very important distinction to keep in mind apart from information hiding and decoupling implementation from the public surface, or API, of a class; validation.
In a public field scenario, there is no way to validate the field's value when it's modified. In case of a public setter (be it a Foo {get; set;} property or a SetFoo(Foo value)) method you have the possibility to add validation code and launch required side-effects and this way ensure that your class is always in a valid or predictable state.
What if you do want to a range check before assignment? That's one of the cases I use setters and getters
More or less simple and realistic example I encountered in practice is an Options class, which has a lot of setters and getters. At some point you might want to add new option which depends on others or has side effects. Or even replace group of options with Enum. In this case setA function will not just modify a field, but will hide some additional configuration logic. Similarly getA will not just return value of a, but something like config == cStuffSupportingA.
Wikipedia has a good overview of [mutator methods(https://en.wikipedia.org/wiki/Mutator_method), which is what setter methods are and how they work in different languages.
The short version: if you want to introduce validation or other logic that gets executed on object modification it is nice to have a setter to put that logic in. Also you may want to hide how you store things. So, those are reasons for having getters/setters. Similarly, for getters, you might have logic that provides default values or values that are dependent on e.g. configuration for things like Locale, character encoding, etc. There are lots of valid reasons to want to have logic other than getting or setting the instance variable.
Obviously, if you have getters and setteres, you don't want people bypassing them by manipulating the object state directly, which is why you should keep instance variables private.
Other things to consider include whether you actually want your objects to be mutable at all (if not, make fields final), whether you want to make modifying the object state threadsafe with e.g. locks, synchronized, etc.
Setting fields as private documents a powerful fact: these private fields are only directly used within the current class. This helps maintainers by not having to track down field usage. They can reason better on the code by looking at the class and determining that the effects on and from these fields with the class' environment go through public and protected method calls. It limits the exposure surface on the class.
In turn, defining a "setter" for a private field is not about giving it publicity again. It is about declaring another powerful fact: an object belonging to this class has a property that can be modified from the outside. (The terms object and property are used in the sense of a bounded part of the whole and an observable fact about this part, not in the OOP sense)
Why then declare a "setter" on a field when making the field public would suffice? Because declaring a field not only binds a name to a property of the objects of the class, but also commits to use memory storage for this property.
Therefore, if you declare a "private field with a setter", you declare three things:
You declare that the name you gave to the field/setter cluster represents a property of the object which is of interest when the object is seen as a black box.
You declare that the value of this property is modifiable by the environment of the object.
You declare that in this particular concrete class, the property of the object is realized by committing some memory storage to it.
I advocate that you never make your fields private with getters and setters indiscriminately. Fields are for describing storage. Methods are for interactions with the environment. (And the particular case of "getters" and "setters" are for describing properties of interest)
My problem is almost exactly the same as the problem posted here: Abstract class with final uninitialized field and I like the solution. However, my problem is a bit more complicated in that the abstract class has multiple final fields of varying types. For example, I have four int, two int[], and two double. What would be the best way to force the subclasses to initialize these variables?
Options I've considered:
Convert all fields to Strings and pass with a Map
Have a really long superclass constructor
Create a helper class that would act as a wrapper and encapsulate all the values, then pass an instance of this class to the base class
The first option is not very elegant, and seems a bit complicated, especially with arrays. The second option is very tedious, and the third option just seems like I'm overdoing it.
Is there a "correct" way of doing this? Or if not, which of the three options posed would be the most elegant?
I would go with the second, "Have a really long superclass constructor." If we follow the approach detailed in the question you referenced, the superclass constructor is protected and not meant to be called by anything external to the class hierarchy or package. My feeling always is, once something is not exposed beyond that boundary - i.e., is not part of the "API" as it were - then it doesn't matter what it looks like. Let it have eight different parameters of varying types, or even more. Yes, it's visible from within the package, but it's clear from the original solution that that constructor is not meant to be called by anything other than the subclasses. That's another motivation for non-public visibility.
Of course, your instincts for doing something cleaner are correct when it comes to public stuff. The fact that you asked this question at all shows you have the right instincts.
Here's another alternative, assuming you have control of all the classes involved: abstract out the fields in the superclass and declare them in the subclasses, sort of like this...
abstract class SuperClass {
abstract int[] getFooArray(); // not public!
abstract int getBar();
}
and then just define the field in each of those subclasses, overriding the methods to return them.
Yes, it will involve some code duplication, but it could very well be cleaner in the end than an unreadably long constructor, and the code you're duplicating isn't very much -- a field, a one-line method to return that field.
However, my problem is a bit more complicated in that the abstract
class has multiple final fields of varying types.
I'm not sure I understand the added complexity in your scenario, but I'm interpreting your issue as : I don't want to have a ton of arguments on my abstract constructor. One possible approach is to have a Builder for the abstract class that is used by the concrete sub classes. The builder is then 'passed up' to the abstract constructor for setting the final fields.
When I have a need for an immutable object (all members are final) that takes many different parameters in the constructor I usually use a Builder pattern.
In this case you can make the builders subclass each other and in this way you will still maintain the ability to extend.
For an example you can see the Guava API for ImmutableCollection Builder.
Or if you don't require immutability, here is an example of CacheBuilder also taken from the same library:
Cache<Key, Graph> graphs = CacheBuilder.newBuilder()
.concurrencyLevel(4)
.weakKeys()
.maximumSize(10000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build(
new CacheLoader<Key, Graph>() {
public Graph load(Key key) throws AnyException {
return createExpensiveGraph(key);
}
});
As you can see the use of a builder replaces the need to pass in 6 parameters in the constructor and makes for more readable/usable code.
If you still don't want to use builders I would go with option (3) as that will prevent some of the hassle of maintaining a very long constructor
which one of below is better or to be prefered
new Object();
Object.setValue1("1");
Object.setValue2("2");
Object.setValue3("3");
or
new Object("1","2","3");
(I assume you're talking about the design of your own classes, rather than how to use other already-designed classes.)
Neither is always "better," it depends on the nature of the object and (to an extent) on your preferred style.
If an object cannot have a meaningful state without some external information, then requiring that information in the constructor makes sense, because then you can't create instances with an invalid state.
However, having constructors that require as little information as possible is useful in terms of making the class easy to use in a variety of situations. If the class is such that a zero-arguments constructor is feasible and doesn't complicate the class, it's great in terms of supporting various use-cases, including cases where the instance is being built as part of parsing some other structure (JSON, XML, etc.).
There is also a third option that builds on the use of fluent interfaces
MyObject obj = new MyObject().setValue1("1").setValue("2").setValue("3");
I personally like this approach but if the number of parameters is short and known at the time of construction AND the varying possible combinations of parameters is short then I would take the route of parameters on the constructor. I think most would agree that 12 constructor overloads are an eye sore.
Depends on whether you know the values at the time of object construction.
If Yes, then use the constructor version if not then you will have to use the other version.
Ofcourse,Initialization through the Constructor version is faster because it involves just one function call over 3 set function calls and also it is more logical way.
Its always better performance to call in constructor If you know values already.
Then there is my preferred alternative. Thing is the name of some interface. It creates an anonymous class.
Thing createThing ( final int val1 , final int val2 , final int val3 )
{
return new Thing ( )
{
// can use val1, val2, val3
} ;
}
It all depends on the application.
Calling Parameterized constructor will be a good idea if at Compile time you know what values to be given to your variables, rather than calling Setters. Because you are calling 3 setter methods and in parameterized constructor, you are just passing to the cnostructor it self.
But if at compile time you don't know what values to be given then how can you call paramterized constructor.
But for initialization it will be better to call parameterized constructor.
There is a semantic difference. If (1) you are instantiating an object with an initial state. In (2) you are changing the state of an existing instance (3 times). It's a small difference but may become very important in more complex systems (especially if you rely on various JavaBean conventions). But still, neither one is wrong or better.
This question already has answers here:
Is it in an anti-pattern to always use get and set methods to access a class's own member fields? [duplicate]
(11 answers)
Closed 9 years ago.
Usually, in my own projects I use getters and setters for any field access, and I followed to do the same on my job. Some time ago, the tech lead of our project asked me why I was doing that and why is this better than just using fields themselves (with an option of declaring them protected if they needed to be accessed by subclasses). I couldn't come up with a clear answer.
So, are there any reasons to using getters and setters inside a class for class' own fields, or is it better to use fields directly?
The most obvious answer is side effects:
int getCost()
{
if (cost == null) {
calculateCost();
}
return cost;
}
If you need the cost, use getCost(). If you want to see if cost has been calculated, use cost.
If there is any business logic around those values (or there is the potential for such logic), then there is a benefit to using getters and setters even for internal calls.
For example, your setter might do validation on its inputs, and throw an exception rather than store an invalid value. Having all your code use that setter rather than simply setting values directly means that the error is caught at the time it is made rather than a long time later when that value is used. A similar case for a getter is when there is a logical default value, which should be used in case of a null. By using a getter, you can safely write local methods without needing continuous null checks or default options.
That said, if there's no business logic in those methods, and no side effects caused by them, then it's mostly a stylistic thing. It is essentially the responsibility of the class to be internally consistent, and as long as it remains so then it's mostly personal/professional preference whether you access the variables directly or through wrapping methods.
You want to declare them as public getters and setters, and private fields. This means external classes (not subclasses) who want to modify the variables all do so through the setters, and get them through the getters. The benefit of this is that if you want to control how or what condition they get or set them, or want to add information or even print debug, it means you only have to put it in the getters and setters.
There's a really good explanation of the benefits on stackoverflow actually:
In Java, difference between default, public, protected, and private
Of course, only make methods when they're actually needed, and similarly, only public when needed by external classes.
Hope that helps the defense!
This is part of the general question as to why you use getters and setters. Many developers use them without though, as a matter of practice. Personally, I only put in getters/setters if I need to.
I would suggest you do what is clearest/simplest to you.
In general, if I can easily add a getter/setter later should I need it, I won't add it. If it would be difficult to add later (or you have an immediate use for them), I would include them.
Some of us are web developers so, we resort to creating JavaBeans and JavaBeans has its own specification. In the specification, it clearly states:
The class must have a public default constructor (no-argument).
The class properties must be accessible using get, set, is (used for boolean properties instead of get) and other methods.
The class should be serializable.
The reason being, JavaBeans were designed for Reusability where JavaBeans could travel through any Java technologies (e.g. Servlets, JSPs, RMI, Web Services, etc.).
That's my 2cent worth on why we have getters/setters. I mostly create JavaBeans.
Some people think that they should always encapsulate all fields by using setters/getters.
Others think that this practice should not be used at all.
If your class does not have any logic for the fields and just is used as a holder, you can skip using methods and just declare your fields as public. This concept is also called a Data Transfer Object (or Messenger.) But as a rule you should use final attribute for such fields to make your class immutable:
public class TwoTuple<A,B> {
public final A first;
public final B second;
public TwoTuple(A a, B b) { first = a; second = b; }
}
However you must/or it's strongly recommended to use setters/getters:
in web applications sometimes there are requirements to use setters/getters. See POJO/JavaBean objects.
if your class is going to be used in concurrent environment. See Java Concurrency in Practice, Section 3.2:
"Whether another thread actually does something with a published reference doesn't really matter, because the risk of misuse is still present.[7] Once an object escapes, you have to assume that another class or thread may, maliciously or carelessly, misuse it. This is a compelling reason to use encapsulation: it makes it practical to analyze programs for correctness and harder to violate design constraints accidentally"
if you want to add some extra logic when you set/get values you must use setters/getters. Just read about encapsulation and its advantages.
My own opinion always declare fields as "private final" and only then, if needed change these properties.
I was thinking how much code one should put in constructors in Java? I mean, very often you make helper methods, which you invoke in a constructor, but sometimes there are some longer initialization things, for example for a program, which reads from a file, or user interfaces, or other programs, in which you don't initialize only the instance variables, in which the constructor may get longer (if you don't use helper methods). I have something in mind that the constructors should generally be short and concise, shouldn't they? Are there exceptions to this?
If you go by the SOLID principles, each class should have one reason to change (i.e. do one thing). Therefore a constructor would normally not be reading a file, but you would have a separate class that builds the objects from the file.
Take a look at this SO question. Even though the other one is for C++, the concepts are still very similar.
As little as is needed to complete the initialization of the object.
If you can talk about a portion (5 or so lines is my guideline) of your constructor as a chunk of logic or a specific process, it's probably best to split it into a separate method for clarity and organizational purposes.
But to each his own.
My customary practice is that if all the constructor has to do is set some fields on an object, it can be arbitrarily long. If it gets too long, it means that the class design is broken anyway, or data need to be packaged in some more complex structures.
If, on the other hand, the input data need some more complex processing before initializing the class fields, I tend to give the constructor the processed data and move the processing to a static factory method.
Constructors should be just long enough, but no longer =)
If you are defining multiple overloaded constructors, don't duplicate code; instead, consolidate functionality into one of them for improved clarity and ease of maintenance.
As Knuth said, "Premature optimization is the root of all evil."
How much should you put in the consructor? Everything you need to. This is the "eager" approach. When--and only when--performance becomes an issue do you consider optimizing it (to the "lazy" or "over-eager" approaches).
Constructors should create the most minimal, generic instance of your object. How generic? Choose the test cases that every instance or object that inherits from the class must pass to be valid - even if "valid" only means fails gracefully (programatically generated exception).
Wikipedia has a good description :
http://en.wikipedia.org/wiki/Constructor_(computer_science)
A Valid object is the goal of the constructor, valid not necessarily useful - that can be done in an initialization method.
Your class may need to be initialized to a certain state, before any useful work can be done with it.
Consider this.
public class CustomerRecord
{
private Date dateOfBirth;
public CustomerRecord()
{
dateOfBirth = new Date();
}
public int getYearOfBirth()
{
Calendar calendar = Calendar.getInstance();
calendar.setTime(dateOfBirth);
return calendar.get(Calendar.YEAR);
}
}
Now if you don't initialize the dateOfBirth member varialble, any subsequent invocation of getYearOfBirth(), will result in a NullPointerException.
So the bare minimum initialization which may involve
Assigning of values.
Invoking helper functions.
to ensure that the class behaves correctly when it's members are invoked later on, is all that needs to be done.
Constructor is like an Application Setup Wizard where you do only configuration. If the Instance is ready to take any (possible) Action on itself then Constructor doing well.