Related
I was reading this answer on SESE about encapsulation and getters/setters. Suppose I favor the use of immutable classes, so if a setter were implemented, it would return the a new object reflecting the change, for example:
//return a new Book reflecting the price change.
public Book updatePrice(double price){}
In the link, the answer suggested I have a method called getDisplayinformation() that returns a data structure.
(think an array indexed by an enum, a struct, or a methodless class)
Following this advice how would I return a Book with a List of authors?
public final class Author{
private final String id;
private final String firstname;
private final String lastname;
//Constructor
}
public final class Book{
private String bookID;
private final String title;
private List<Author> authorsList;
private double price;
//Constructor
}
Suppose I wanted to return a Map<String,String>.
public Map<String,String> getDisplayinformation(){
Map<String,String> displayMap = new HashMap<String,String>();
display.put("BookTitle", title);
display.put("ID", bookID);
display.put("Price", price.toString())
//insert authorsList;
return displayMap;
}
The answer you quote got half of it right. Providing getters for fields does break encapsulation, because it makes the caller dependent on some internal structure.
Now, returning a map where the caller needs to know the keys and knows what that information is, is basically not different than providing a getter for that field.
Object-orientation tries to tell us that the functionality needs to be bundled with the data. So, the Book has to have some method to present the Book. I would not call it getDisplayInformation(), rather simply display(). It can return something, and it can take relevant parameters too.
The point is, that anything returned by display() must be about the presentation, and must not be about the book. Semantics about being a book should be lost at that point, otherwise the caller will be tightly coupled.
So, it's ok to return an XML document, JSON document, HTML, a Wicket Component, whatever it is you can use for presentation that is independent of the Book.
Or, the method could take an argument to present itself to. Like AWT Component.paint(Graphics g) or something.
Note: this is actually a controversial subject. Mixed-paradigm development (a mix of procedural and ood) would argue that presentation needs to be separated from objects, while object-orientation argues that data and function belong always together.
How can I use the set and get methods, and why should I use them? Are they really helpful? And also can you give me examples of set and get methods?
Set and Get methods are a pattern of data encapsulation. Instead of accessing class member variables directly, you define get methods to access these variables, and set methods to modify them. By encapsulating them in this manner, you have control over the public interface, should you need to change the inner workings of the class in the future.
For example, for a member variable:
Integer x;
You might have methods:
Integer getX(){ return x; }
void setX(Integer x){ this.x = x; }
chiccodoro also mentioned an important point. If you only want to allow read access to the field for any foreign classes, you can do that by only providing a public get method and keeping the set private or not providing a set at all.
I want to add to other answers that setters can be used to prevent putting the object in an invalid state.
For instance let's suppose that I've to set a TaxId, modelled as a String. The first version of the setter can be as follows:
private String taxId;
public void setTaxId(String taxId) {
this.taxId = taxId;
}
However we'd better prevent the use to set the object with an invalid taxId, so we can introduce a check:
private String taxId;
public void setTaxId(String taxId) throws IllegalArgumentException {
if (isTaxIdValid(taxId)) {
throw new IllegalArgumentException("Tax Id '" + taxId + "' is invalid");
}
this.taxId = taxId;
}
The next step, to improve the modularity of the program, is to make the TaxId itself as an Object, able to check itself.
private final TaxId taxId = new TaxId()
public void setTaxId(String taxIdString) throws IllegalArgumentException {
taxId.set(taxIdString); //will throw exception if not valid
}
Similarly for the getter, what if we don't have a value yet? Maybe we want to have a different path, we could say:
public String getTaxId() throws IllegalStateException {
return taxId.get(); //will throw exception if not set
}
I think you want something like this:
public class Person {
private int age;
//public method to get the age variable
public int getAge(){
return this.age
}
//public method to set the age variable
public void setAge(int age){
this.age = age;
}
}
You're simply calling such a method on an object instance. Such methods are useful especially if setting something is supposed to have side effects. E.g. if you want to react to certain events like:
public void setAge(int age){
this.age = age;
double averageCigarettesPerYear = this.smokedCigarettes * 1.0 / age;
if(averageCigarettesPerYear >= 7300.0) {
this.eventBus.fire(new PersonSmokesTooMuchEvent(this));
}
}
Of course this can be dangerous if somebody forgets to call setAge(int) where he should and sets age directly using this.age.
Setters and getters are used to replace directly accessing member variables from external classes. if you use a setter and getter in accessing a property, you can include initialization, error checking, complex transformations, etc. Some examples:
private String x;
public void setX(String newX) {
if (newX == null) {
x = "";
} else {
x = newX;
}
}
public String getX() {
if (x == null) {
return "";
} else {
return x;
}
}
Having accessor methods is preferred to accessing fields directly, because it controls how fields are accessed (may impose data checking etc) and fits with interfaces (interfaces can not requires fields to be present, only methods).
Some benefits of using getters and setters (known as encapsulation or data-hiding):
(originally answered here)
1. The fields of a class can be made read-only (by only providing the getter) or write-only (by only providing the setter). This gives the class a total control of who gets to access/modify its fields.
Example:
class EncapsulationExample {
private int readOnly = -1; // this value can only be read, not altered
private int writeOnly = 0; // this value can only be changed, not viewed
public int getReadOnly() {
return readOnly;
}
public int setWriteOnly(int w) {
writeOnly = w;
}
}
2. The users of a class do not need to know how the class actually stores the data. This means data is separated and exists independently from the users thus allowing the code to be more easily modified and maintained. This allows the maintainers to make frequent changes like bug fixes, design and performance enhancements, all while not impacting users.
Furthermore, encapsulated resources are uniformly accessible to each user and have identical behavior independent of the user since this behavior is internally defined in the class.
Example (getting a value):
class EncapsulationExample {
private int value;
public int getValue() {
return value; // return the value
}
}
Now what if I wanted to return twice the value instead? I can just alter my getter and all the code that is using my example doesn't need to change and will get twice the value:
class EncapsulationExample {
private int value;
public int getValue() {
return value*2; // return twice the value
}
}
3. Makes the code cleaner, more readable and easier to comprehend.
Here is an example:
No encapsulation:
class Box {
int widthS; // width of the side
int widthT; // width of the top
// other stuff
}
// ...
Box b = new Box();
int w1 = b.widthS; // Hm... what is widthS again?
int w2 = b.widthT; // Don't mistake the names. I should make sure I use the proper variable here!
With encapsulation:
class Box {
private int widthS; // width of the side
private int widthT; // width of the top
public int getSideWidth() {
return widthS;
}
public int getTopWIdth() {
return widthT;
}
// other stuff
}
// ...
Box b = new Box();
int w1 = b.getSideWidth(); // Ok, this one gives me the width of the side
int w2 = b.getTopWidth(); // and this one gives me the width of the top. No confusion, whew!
Look how much more control you have on which information you are getting and how much clearer this is in the second example. Mind you, this example is trivial and in real-life the classes you would be dealing with a lot of resources being accessed by many different components. Thus, encapsulating the resources makes it clearer which ones we are accessing and in what way (getting or setting).
Here is good SO thread on this topic.
Here is good read on data encapsulation.
The above answers summarize the role of getters and setters better than I could, however I did want to add that your code should ideally be structured to reduce the use of pure getters and setters, i.e. those without complex constructions, validation, and so forth, as they break encapsulation. This doesn't mean you can't ever use them (stivlo's answer shows an example of a good use of getters and setters), just try to minimize how often you use them.
The problem is that getters and setters can act as a workaround for direct access of private data. Private data is called private because it's not meant to be shared with other objects; it's meant as a representation of the object's state. Allowing other objects to access an object's private fields defeats the entire purpose of setting it private in the first place. Moreover, you introduce coupling for every getter or setter you write. Consider this, for example:
private String foo;
public void setFoo(String bar) {
this.foo = bar;
}
What happens if, somewhere down the road, you decide you don't need foo anymore, or you want to make it an integer? Every object that uses the setFoo method now needs to be changed along with foo.
just because the OOP rule: Data Hiding and Encapsulation. It is a very bad practice to declare a object's as public and change it on the fly in most situations. Also there are many other reasons , but the root is Encapsulation in OOP. and "buy a book or go read on Object Oriented Programming ", you will understand everything on this after you read any book on OOP.
The benefits of get() set() methods are as follows ..
You can serialize you object easily.
You can create a persistent object from the containing class.
You can convert the properties to JSON easily.
In the DAO layer (Frameworks like Hibernate) you can directly save the object to DB.
Easy understanding of object oriented concept.
Needs in all design pattern except possibly in single tone pattern.
Security for properties protecting direct access.
Polymorphism, Encapsulation can be easily understood and implemented by this type of class.
Example:
private String personName;
private int personId;
public void setPersonName(String name) throws Exception{
if(!(name.equals("")||name=="")){
this.personName = name;
}
}
public String getPersonName(){
return this.personName;
}
public void setPersonId(int id) throws Exception{
this.personId = id;
}
public int getPersonId(){
return this.personId;
}
Above answers all assume that the object in question is an object with behaviour.
An advanced strategy in OOP is to separate data objects (that do zip, only have fields) and behaviour objects.
With data objects, it is perfectly fine to omit getters and instead have public fields. They usually don't have setters, since they most commonly are immutable - their fields are set via the constructors, and never again.
Have a look at Bob Martin's Clean Code or Pryce and Freeman's Growing OO Software... for details.
public class Person{
private int age;
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
}
i think this is you want..
and this also called pojo
this is the code for set method
public void setAge(int age){
this.age = age;
}
It looks like you trying to do something similar to C# if you want setAge create method setAge(int age){
this.age = age;}
I don't see a simple answer to the second question (why) here. So here goes.
Let's say you have a public field that gets used very often in your code. Whenever you decide you need to do something extra before you give or set this field you have a problem. You have to create a special getter and setter for this field and change your complete code from using the field directly to using the getter and setters.
Now imagine you are developing a library widely used by many people. When you need to make a change like the above and set direct access of the field to private the code of all the people using this field will break.
Using getters and setters is about future planning of the code, it makes it more flexible. Of course you can use public fields, especially for simple classes that just hold some data. But it's always a good idea to just make the field privately and code a get and set method for it.
This answer is merged from another question.
Your getAge() method is called instance method in Java.
To invoke an instance method, you should have a object of the Class in which this method is defined.
For Example, If this method in a Class called Person, then
Create a Person object using new operator
Person p = new Person();
To get the age of a Person object, use this method
p.getAge()
Although still a second year undergraduate student I will say my opinion. I believe that Java and private variables within your class are "RULES". Therefore because the variables in your class are private I think you use getters and setters to be able to define these variables outside the class.
I have started playing around with immutable value objects in Java while working on a game project, following the "public final fields" approach:
public class Team {
public final String name, flag;
public Team(String name, String flag) {
this.name = name;
this.flag = flag;
}
}
This works pretty well for me so far, but I need different sets of extra information about the team in different circumstances. For example, a team has a set color during a match. The question is, what is the best way to deal with these sets of extended information? I know this is a fairly general question, but I want to keep using immutable objects and that might influence the solution.
Here are the options I have come up with. Most of them are probably "good enough", but I'd like to learn some arguments for and against them for future reference.
Option 1: Everything in one class
public class Team {
public final String name, flag, colorName;
public final int colorRgb;
public Team(String name, String flag, String colorName, int colorRgb) {
this.name = name;
this.flag = flag;
this.colorName = colorName;
this.colorRgb = colorRgb;
}
}
This takes only one class for all uses, but there is no type-based indication of what extra data is expected/provided.
Option 2: Subclassing
public class TeamWithColor extends Team {
public final String colorName;
public final int colorRgb;
public Team(String name, String flag, String colorName, int colorRgb) {
super(name, flag);
this.colorName = colorName;
this.colorRgb = colorRgb;
}
}
This might make a content-based equals() implementation impossible.
Option 3: Composition
public class TeamWithColor {
public final Team team;
public final String colorName;
public final int colorRgb;
public Team(Team team, String colorName, int colorRgb) {
this.team = team;
this.colorName = colorName;
this.colorRgb = colorRgb;
}
}
Less copying / boilerplate code if the team data and extra data often change independently.
Option 4: Pair/Tuple (using an immutable Pair class)
public class TeamColor {
public final String colorName;
public final int colorRgb;
public Team(String colorName, int colorRgb) {
this.colorName = colorName;
this.colorRgb = colorRgb;
}
}
Pair<Team, TeamColor> teamWithColor = Pair.create(team, teamColor);
... or with a custom class that ties Team and TeamColor together.
I tend toward option 3 or 4, but I'm interested in your opinions, arguments and gut feelings :)
As you said. The team can appear in different circumstances.
These circumstances are the context giving the team the additional attributes.
Therefore I suggest using composition for each different context that add's data.
public class TeamWithColor {
public final Team team;
public final TeamColor teamColor;
public TeamWithColor(Team team, TeamColor teamColor) {
this.team = team;
this.teamColor = teamColor;
}
}
Maybe you'll have :
public class TeamDuringOlimpics{
public final Team team;
public final TeamColor teamColor;
public final TeamFlag teamFlag;
public TeamDuringOlimpics(Team team, TeamColor teamColor, TeamFlag teamFlagTeamFlag teamFlag) {
this.team = team;
this.teamColor = teamColor;
this.teamFlag = teamFlag;
}
}
Composition sounds like a good option for adding contextual data that is required to be mutable.
In Java immutable classes are usually marked final and cannot be extended. See String as an example. That rules out option number 2.
Be weary of using Pairs. There are many good reasons the Pair type has not been added to Java. In this case your data is better modeled by creating a new data type (i.e. thru composition).
Recommended best practices for creating immutable classes: http://www.javapractices.com/topic/TopicAction.do?Id=29
If an immutable class is inheritable, or if contains aspects whose types could be mutable, then it will have no security against mischief. A "immutable" interface will likewise have no security. Likewise also if an object has any members of extensible types, and object is regarded as containing any of the information in the objects referred to by those members. It is up to you to decide whether or not that is a problem. Immutable interfaces and extensible mutable classes may be much more versatile than deeply-sealed ones; if a class isn't going to be deeply sealed, there's little security advantage to making it partially so.
Note that it is possible for a deeply-immutable object to have a field which is of a mutable type, if the semantics of the field specify that it identifies, rather than contains, the object in question. For example, it may be useful to have have a "snapshot" object which contains references to some mutable objects and, for each object, an immutable copy of its current state; the "snapshot" object would then expose a method of restoring each object to the state it had when the snapshot was generated. The snapshot object would be "deeply immutable" despite its reference to a mutable object, since the snapshot's references to the mutable objects exist purely to identify them, and the identities of those objects wouldn't change even if their state does.
One pattern that I like in .net, which should also work in Java, is to have interfaces like IReadableFoo and IImmutableFoo; the latter would inherit the former but not add any new members. The interface IReadableFoo should contain, in addition to members to read its properties, a member AsImmutable() which would return an IImmutableFoo. This approach allows code to use mutable types when convenient, while minimizing redundant defensive copying (code which wants to persist something must call AsImmutable() on it; if the object in question is mutable, that action will create an immutable copy, but if the object is already immutable, no new copy will be required).
You could consider keeping this piece of information outside the Team object. For instance, you could have a Map or Map
This way, you could enrich your objects with many additional values without introducing new classes or modifying existing classes. Moreover, it would keep the immutable property of the other objects.
I recommend the Decorator pattern.
public class TeamWithColor extends Team {
public final Team team;
public final String colorName;
public final int colorRgb;
public Team(Team team, String colorName, int colorRgb) {
this.team = team;
this.colorName = colorName;
this.colorRgb = colorRgb;
}
}
http://en.wikipedia.org/wiki/Decorator_pattern
I usually try to avoid putting everything in one class (option 1) this leaves us 4 options
in case I needed the class to be thread-safe I favor using a volatile/AtomicReference of an Immutable tuple (option 4) instead of using locks and other blocking syncs (let's call it: option 5)
if thread-safety isn't a concern then I would pick Composition (option 3) over In inheritance (option 2) unless an IS-A relation naturally exist
a Colored Team IS a Team after all, so I would be nice to exploit this relation. if I were you I would code it like this:
public final class ColoredTeam extends AbstractTeam implements Team {
// the rest comes along intuitively
}
since "AbstractTeam" is abstract, content-based equals() implementation is perfectly fine as long "ColoredTeam" itself has no subclasses, I made ColoredTeam final to achieve this but I could have made the contractor private, throws an exception, etc.
How can I use the set and get methods, and why should I use them? Are they really helpful? And also can you give me examples of set and get methods?
Set and Get methods are a pattern of data encapsulation. Instead of accessing class member variables directly, you define get methods to access these variables, and set methods to modify them. By encapsulating them in this manner, you have control over the public interface, should you need to change the inner workings of the class in the future.
For example, for a member variable:
Integer x;
You might have methods:
Integer getX(){ return x; }
void setX(Integer x){ this.x = x; }
chiccodoro also mentioned an important point. If you only want to allow read access to the field for any foreign classes, you can do that by only providing a public get method and keeping the set private or not providing a set at all.
I want to add to other answers that setters can be used to prevent putting the object in an invalid state.
For instance let's suppose that I've to set a TaxId, modelled as a String. The first version of the setter can be as follows:
private String taxId;
public void setTaxId(String taxId) {
this.taxId = taxId;
}
However we'd better prevent the use to set the object with an invalid taxId, so we can introduce a check:
private String taxId;
public void setTaxId(String taxId) throws IllegalArgumentException {
if (isTaxIdValid(taxId)) {
throw new IllegalArgumentException("Tax Id '" + taxId + "' is invalid");
}
this.taxId = taxId;
}
The next step, to improve the modularity of the program, is to make the TaxId itself as an Object, able to check itself.
private final TaxId taxId = new TaxId()
public void setTaxId(String taxIdString) throws IllegalArgumentException {
taxId.set(taxIdString); //will throw exception if not valid
}
Similarly for the getter, what if we don't have a value yet? Maybe we want to have a different path, we could say:
public String getTaxId() throws IllegalStateException {
return taxId.get(); //will throw exception if not set
}
I think you want something like this:
public class Person {
private int age;
//public method to get the age variable
public int getAge(){
return this.age
}
//public method to set the age variable
public void setAge(int age){
this.age = age;
}
}
You're simply calling such a method on an object instance. Such methods are useful especially if setting something is supposed to have side effects. E.g. if you want to react to certain events like:
public void setAge(int age){
this.age = age;
double averageCigarettesPerYear = this.smokedCigarettes * 1.0 / age;
if(averageCigarettesPerYear >= 7300.0) {
this.eventBus.fire(new PersonSmokesTooMuchEvent(this));
}
}
Of course this can be dangerous if somebody forgets to call setAge(int) where he should and sets age directly using this.age.
Setters and getters are used to replace directly accessing member variables from external classes. if you use a setter and getter in accessing a property, you can include initialization, error checking, complex transformations, etc. Some examples:
private String x;
public void setX(String newX) {
if (newX == null) {
x = "";
} else {
x = newX;
}
}
public String getX() {
if (x == null) {
return "";
} else {
return x;
}
}
Having accessor methods is preferred to accessing fields directly, because it controls how fields are accessed (may impose data checking etc) and fits with interfaces (interfaces can not requires fields to be present, only methods).
Some benefits of using getters and setters (known as encapsulation or data-hiding):
(originally answered here)
1. The fields of a class can be made read-only (by only providing the getter) or write-only (by only providing the setter). This gives the class a total control of who gets to access/modify its fields.
Example:
class EncapsulationExample {
private int readOnly = -1; // this value can only be read, not altered
private int writeOnly = 0; // this value can only be changed, not viewed
public int getReadOnly() {
return readOnly;
}
public int setWriteOnly(int w) {
writeOnly = w;
}
}
2. The users of a class do not need to know how the class actually stores the data. This means data is separated and exists independently from the users thus allowing the code to be more easily modified and maintained. This allows the maintainers to make frequent changes like bug fixes, design and performance enhancements, all while not impacting users.
Furthermore, encapsulated resources are uniformly accessible to each user and have identical behavior independent of the user since this behavior is internally defined in the class.
Example (getting a value):
class EncapsulationExample {
private int value;
public int getValue() {
return value; // return the value
}
}
Now what if I wanted to return twice the value instead? I can just alter my getter and all the code that is using my example doesn't need to change and will get twice the value:
class EncapsulationExample {
private int value;
public int getValue() {
return value*2; // return twice the value
}
}
3. Makes the code cleaner, more readable and easier to comprehend.
Here is an example:
No encapsulation:
class Box {
int widthS; // width of the side
int widthT; // width of the top
// other stuff
}
// ...
Box b = new Box();
int w1 = b.widthS; // Hm... what is widthS again?
int w2 = b.widthT; // Don't mistake the names. I should make sure I use the proper variable here!
With encapsulation:
class Box {
private int widthS; // width of the side
private int widthT; // width of the top
public int getSideWidth() {
return widthS;
}
public int getTopWIdth() {
return widthT;
}
// other stuff
}
// ...
Box b = new Box();
int w1 = b.getSideWidth(); // Ok, this one gives me the width of the side
int w2 = b.getTopWidth(); // and this one gives me the width of the top. No confusion, whew!
Look how much more control you have on which information you are getting and how much clearer this is in the second example. Mind you, this example is trivial and in real-life the classes you would be dealing with a lot of resources being accessed by many different components. Thus, encapsulating the resources makes it clearer which ones we are accessing and in what way (getting or setting).
Here is good SO thread on this topic.
Here is good read on data encapsulation.
The above answers summarize the role of getters and setters better than I could, however I did want to add that your code should ideally be structured to reduce the use of pure getters and setters, i.e. those without complex constructions, validation, and so forth, as they break encapsulation. This doesn't mean you can't ever use them (stivlo's answer shows an example of a good use of getters and setters), just try to minimize how often you use them.
The problem is that getters and setters can act as a workaround for direct access of private data. Private data is called private because it's not meant to be shared with other objects; it's meant as a representation of the object's state. Allowing other objects to access an object's private fields defeats the entire purpose of setting it private in the first place. Moreover, you introduce coupling for every getter or setter you write. Consider this, for example:
private String foo;
public void setFoo(String bar) {
this.foo = bar;
}
What happens if, somewhere down the road, you decide you don't need foo anymore, or you want to make it an integer? Every object that uses the setFoo method now needs to be changed along with foo.
just because the OOP rule: Data Hiding and Encapsulation. It is a very bad practice to declare a object's as public and change it on the fly in most situations. Also there are many other reasons , but the root is Encapsulation in OOP. and "buy a book or go read on Object Oriented Programming ", you will understand everything on this after you read any book on OOP.
The benefits of get() set() methods are as follows ..
You can serialize you object easily.
You can create a persistent object from the containing class.
You can convert the properties to JSON easily.
In the DAO layer (Frameworks like Hibernate) you can directly save the object to DB.
Easy understanding of object oriented concept.
Needs in all design pattern except possibly in single tone pattern.
Security for properties protecting direct access.
Polymorphism, Encapsulation can be easily understood and implemented by this type of class.
Example:
private String personName;
private int personId;
public void setPersonName(String name) throws Exception{
if(!(name.equals("")||name=="")){
this.personName = name;
}
}
public String getPersonName(){
return this.personName;
}
public void setPersonId(int id) throws Exception{
this.personId = id;
}
public int getPersonId(){
return this.personId;
}
Above answers all assume that the object in question is an object with behaviour.
An advanced strategy in OOP is to separate data objects (that do zip, only have fields) and behaviour objects.
With data objects, it is perfectly fine to omit getters and instead have public fields. They usually don't have setters, since they most commonly are immutable - their fields are set via the constructors, and never again.
Have a look at Bob Martin's Clean Code or Pryce and Freeman's Growing OO Software... for details.
public class Person{
private int age;
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
}
i think this is you want..
and this also called pojo
this is the code for set method
public void setAge(int age){
this.age = age;
}
It looks like you trying to do something similar to C# if you want setAge create method setAge(int age){
this.age = age;}
I don't see a simple answer to the second question (why) here. So here goes.
Let's say you have a public field that gets used very often in your code. Whenever you decide you need to do something extra before you give or set this field you have a problem. You have to create a special getter and setter for this field and change your complete code from using the field directly to using the getter and setters.
Now imagine you are developing a library widely used by many people. When you need to make a change like the above and set direct access of the field to private the code of all the people using this field will break.
Using getters and setters is about future planning of the code, it makes it more flexible. Of course you can use public fields, especially for simple classes that just hold some data. But it's always a good idea to just make the field privately and code a get and set method for it.
This answer is merged from another question.
Your getAge() method is called instance method in Java.
To invoke an instance method, you should have a object of the Class in which this method is defined.
For Example, If this method in a Class called Person, then
Create a Person object using new operator
Person p = new Person();
To get the age of a Person object, use this method
p.getAge()
Although still a second year undergraduate student I will say my opinion. I believe that Java and private variables within your class are "RULES". Therefore because the variables in your class are private I think you use getters and setters to be able to define these variables outside the class.
First of all I should probably say that the term 'constant object' is probably not quite right and might already mean something completely different from what I am thinking of, but it is the best term I can think of to describe what I am talking about.
So basically I am designing an application and I have come across something that seems like there is probably an existing design pattern for but I don't know what it is or what to search for, so I am going to describe what it is I am trying to do and I am looking for suggestions as to the best way to implement it.
Lets say you have a class:
public class MyClass {
private String name;
private String description;
private int value;
public MyClass(String name, String description, int value) {
this.name = name;
this.description = description;
this.value = value;
}
// And I guess some getters and setters here.
}
Now lets say that you know in advance that there will only ever be say 3 instances of this class, and the data is also known in advance (or at least will be read from a file at runtime, and the exact filename is known in advance). Basically what I am getting at is that the data is not going to be changed during runtime (once it has been set).
At first I thought that I should declare some static constants somewhere, e.g.
public static final String INSTANCE_1_DATA_FILE = "path/to/instance1/file";
public static final String INSTANCE_2_DATA_FILE = "path/to/instance2/file";
public static final String INSTANCE_3_DATA_FILE = "path/to/instance3/file";
public static final MyClass INSTANCE_1 = new MyClass(getNameFromFile(INSTANCE_1_DATA_FILE), getDescriptionFromFile(INSTANCE_1_DATA_FILE), getValueFromFile(INSTANCE_1_DATA_FILE));
public static final MyClass INSTANCE_2 = new MyClass(getNameFromFile(INSTANCE_2_DATA_FILE), getDescriptionFromFile(INSTANCE_2_DATA_FILE), getValueFromFile(INSTANCE_2_DATA_FILE));
public static final MyClass INSTANCE_3 = new MyClass(getNameFromFile(INSTANCE_3_DATA_FILE), getDescriptionFromFile(INSTANCE_3_DATA_FILE), getValueFromFile(INSTANCE_3_DATA_FILE));
Obvisouly now, whenever I want to use one of the 3 instances I can just refer directly to the constants.
But I started thinking that there might be a cleaner way to handle this and the next thing I thought about was doing something like:
public MyClassInstance1 extends MyClass {
private static final String FILE_NAME = "path/to/instance1/file";
public String getName() {
if (name == null) {
name = getNameFromFile(FILE_NAME);
}
return name;
}
// etc.
}
Now whenever I want to use the instances of MyClass I can just use the one I want e.g.
private MyClass myInstance = new MyClassInstance2();
Or probably even better would be to make them singletons and just do:
private MyClass myInstance = MyClassInstance3.getInstance();
But I can't help but think that this is also not the right way to handle this situation. Am I overthinking the problem? Should I just have a switch statement somewhere e.g.
public class MyClass {
public enum Instance { ONE, TWO, THREE }
public static String getName(Instance instance) {
switch(instance) {
case ONE:
return getNameFromFile(INSTANCE_1_DATA_FILE);
break;
case TWO:
etc.
}
}
}
Can anyone tell me the best way to implement this? Note that I have written the sample code in Java because that is my strongest language, but I will probably be implementing the application in C++, so at the moment I am more looking for language independent design patterns (or just for someone to tell me to go with one of the simple solutions I have already mentioned).
If you want the values to be constant, then you will not need setters, otherwise code can simply change the values in your constants, making them not very constant. In C++, you can just declare the instances const, although I'd still get rid of the setters, since someone could always cast away the const.
The pattern looks ok, although the fact that you are creating a new instance each time one is requested, is not usual for constants.
In java, you can create enums that are "smart" e.g.
public enum MyClass {
ONE(INSTANCE_1_DATA_FILE),
TWO(INSTANCE_2_DATA_FILE),
//etc...
private MyClass(String dataFile)
{
this(getNameFromDataFile(dataFile), other values...)
}
private MyClass(String name, String data, etc...)
{
this.name = name;
// etc..
}
public String getName()
{
return name;
}
}
In C++, you would create your MyClass, with a private constructor that takes the filename and whatever else it needs to initialize, and create static const members in MyClass for each instance, with the values assigned a new instance of MyClass created using the private constructor.
EDIT: But now I see the scenario I don't think this is a good idea having static values. If the types of ActivityLevel are fundamental to your application, then you can enumerate the different type of activity level as constants, e.g. a java or string enum, but they are just placeholders. The actual ActivityDescription instances should come from a data access layer or provider of some kind.
e.g.
enum ActivityLevel { LOW, MED, HIGH }
class ActivityDescription
{
String name;
String otherDetails;
String description; // etc..
// perhaps also
// ActivityLevel activityLevel;
// constructor and getters
// this is an immutable value object
}
interface ActivityDescriptionProvider
{
ActivityDescription getDescription(ActivityLevel activityLevel);
}
You can implement the provider using statics if you want, or an enum of ActivityDescription instnaces, or better still a Map of ActivityLevel to ActivityDescription that you load from a file, fetch from spring config etc. The main point is that using an interface to fetch the actual description for a given ActivityLevel decouples your application code from the mechanics of how those descriptions are produced in the system. It also makes it possible to mock the implementation of the interface when testing the UI. You can stress the UI with a mock implementation in ways that is not possible with a fixed static data set.
Now lets say that you know in advance that there will only ever be say 3 instances of this class, and the data is also known in advance (or at least will be read from a file at runtime, and the exact filename is known in advance). Basically what I am getting at is that the data is not going to be changed during runtime (once it has been set).
I'd use an enum. And then rather in this flavor:
public enum MyEnum {
ONE("path/to/instance1/file"),
TWO("path/to/instance2/file"),
THREE("path/to/instance3/file");
private String name;
private MyEnum(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Which can be used as follows:
MyEnum one = MyEnum.ONE;
String name = one.getName();
(I'm too slow once again, you already accepted an answer, but here it is anyway...)
You want to (a) prevent changes to the data held in objects of MyClass, and (b) allow only a fixed set of MyClass objects to exist, implying that runtime code should not be able to create new instances of MyClass.
Your initial example has a public constructor, which violates (b)
I'd use a Factory approach so the Factory is the only thing that can create instances, and the class doesn't provide any setters so it's immutable.
Depending on how much flexibility you want for the future, you could put the factory and the class in the same package and limit scope that way, or you could make MyClass an inner class within the factory. You may also consider making MyClass an interface separate from its implementation.
A properties file could be used to configure the factory itself.
The properties file (e.g. "foo.properties") could look something like
one=/path/to/datafile1
two=/another/path/to/datafile2
three=/path/to/datafile3
I use "Foo" instead of "MyClass" in the (Java) examples below.
public class FooFactory
{
/** A place to hold the only existing instances of the class */
private final Map<String, Foo> instances = new HashMap<String, Foo>();
/** Creates a factory to manufacture Foo objects */
// I'm using 'configFile' as the name of a properties file,
// but this could use a Properties object, or a File object.
public FooFactory(String configfile)
{
Properties p = new Properties();
InputStream in = this.getClass().getResourceAsStream();
p.load(in); // ignoring the fact that IOExceptions can be thrown
// Create all the objects as specified in the factory properties
for (String key : p.keys())
{
String datafile = p.getProperty(key);
Foo obj = new Foo(datafile);
instances.put(key, obj);
}
}
public Foo getFoo(String which)
{
return instances.get(which);
}
/** The objects handed out by the factory - your "MyClass" */
public class Foo
{
private String name;
private String description;
private int value;
private Foo(String datafile)
{
// read the datafile to set name, description, and value
}
}
}
You're set to allow only your predefined instances, which can't be changed at runtime, but you can set it all up differently for another run at a later time.
Your first method seems to me like the best and the least prone to code rot. I'm not impressed by the idea of subclassing an object just to change the file name that contains the data that will be used to build it.
Of course, you could maybe improve on your original idea by wrapping these all in an outer class that provides some sort of enumeration access. A collection of MyClass's in other words. But I think you should discard this subclassing idea.
First, you really should be limiting where you use these instances in the code. Use them in as few places as possible. Given these are file names, I expect you want three class instances which accesses the files. How many classes are required depends on what your want to do with them? Look at the Singleton pattern for these classes.
Now you don't need the constants, but could have a helper class which will read the file containing the file names and supply them to the reader class. The code to find then name could also be a method called by the static initializer of the Singleton.
The common approach is to use a map:
private static final Map<String, YouClass> mapIt =
new HashMap<String, YouClass>(){{
put("one", new YourClass("/name", "desc", 1 )),
put("two", new YourClass("/name/two", "desc2", 2 )),
put("three", new YourClass("/name/three", "desc", 3 ))
}}
public static YourClass getInstance( String named ) {
return mapIt.get( named );
}
Next time you need it:
YouClass toUse = YourClass.getInstance("one");
Probably using strings as keys is not the best option but you get the idea.