The Play! framework generates getters and setters for each public field of a model class at runtime.
public class Product {
public String name;
public Integer price;
}
will be transformed to
public class Product {
public String name;
public Integer price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
}
The manual explains further:
Then when you want to access a property you can just write:
product.name = "My product";
product.price = 58;
Which is translated at load time to:
product.setName("My product");
product.setPrice(58);
... and warns:
You can’t directly use getter and setter methods to access properties
if you rely on automatic generation. These methods are generated at
runtime. So if you reference them in code you write, the compiler
won’t find the methods and will generate an error.
Since I cannot use these getters and setters from outside of the Play! project, I see no benefit in generating them. What is the benefit compared to public fields, refactorings (encapsulate a field and change the callers) of all modern IDEs taken into account?
Short answer: Beans require them.
Longer: Beans specification requires (amongst other things) getter/setter for each internal field. I'm not 100% sure, but I assume both Hibernate and Groovy templates expect Java Beans (the POJO Beans, not the Java EE one!), thus they'll ask for getters/setters. Play just saves you time doing that, so you don't have to worry with boiler-plate code (unless you want to define your own getter/setter for some reason, which you can do).
Another reason,, is although you don't have to specify the setters and getters, you still can!
So, if you have (per your example)
product.name = "my product"
That's fine, and makes your code quicker and in my opinion easier to read. However, there is a good reason for setters and getters for encapsulation. If you wanted to add some logic when your product.name is changed, you can specify your own setter, but you don't have to change the code above, as it will continue to call the setter behind the scenes.
So, this gives you the flexibility and power of good encapsulation, but the neatness and readability of direct field access.
I my opinion this is the best of both worlds.
If you have a private getter/setter method, then this will not work as it is not possible to create a public getter/setter method with same name. So it will fail at run time!
Related
Is a realization of POM an example of encapsulation? Are all imported libraries, code builders (maven/gradel/..) and all used code in the project, which realization is based behind "closed doors", examples of encapsulation?
It is hard to say whether Page Object Model is an example of encapsulation. However, as wiki says about encapsulation:
In object-oriented programming (OOP), encapsulation refers to the
bundling of data with the methods that operate on that data, or the
restricting of direct access to some of an object's components. Encapsulation is used to hide the values or state of a structured
data object inside a class, preventing direct access to them by
clients in a way that could expose hidden implementation details or
violate state invariance maintained by the methods.
So if Page Object Model hides the values or state from direct access by other users, then it can be said that it is an exmaple of encapsulation.
One of the ways to achieve encapsulation is to use setter and getter methods and access modifiers. Let me show an example:
public class EncapsulatedPerson
{
private string name;
public string GetName()
{
return name;
}
public void SetName(string name)
{
this.name = name;
}
}
and Person without encapsulation. Any user of class NotEncapsulatedPerson can edit name:
public class NotEncapsulatedPerson
{
public string name;
}
I created my JPA entities via reverse engineering in netbeans and i also added some calculated values to my entities like; i have name and surname fields in the users table and i created a method in user entity like
public String getDisplayName()
{
return name + " " + surname;
}
And i have several of this and in addition i've overridden some superclass methods like compareTo(), toString()
What i want to do is to seperate these methods so when i regenerate the entities i'll not have to add these methods manually again and again.
As i know, you can not seperate a class to multiple files in java.
I tried inheritance as well but i'm not sure what is going to be the best practice.
Regards.
Basically, if you want to share some code between 2 classes, there are only 2 possibilities:
Inheritance, where the shared code is delegated to an abstract class and the concrete implementations extend it. If you use it in JPA, you have to be aware that data bases (generally) do not support such approach and you have to design the mapping (https://thorben-janssen.com/complete-guide-inheritance-strategies-jpa-hibernate/).
Composition, where the shared code is encapsulated in a separate class used as a field type in concrete implementation.
Example of the latter:
#Entity
public class PersonalData {
private String name;
private String surname;
public String getDisplayName() {
return name + " " + surname;
}
}
#Entity
public class User {
private PersonalData data;
}
Additionally, to avoid boilerplate code creation, you can use Lombok: https://projectlombok.org/
This question already has answers here:
Property and Encapsulation
(4 answers)
Closed 7 years ago.
I've just learned about OOP. I'm kind of confused about private members in a class.
I saw examples about setting variable members to private so it's not be changed anywhere else.
But on the other hand, there are public methods like getName() and setName() to get and set the private member Name for instance.
What is different between changing it through methods and changing it directly? Can anyone explain it for me, please?
The main argument for this pattern is encapsulation as described in this answer.
But admittedly in your name example there is not much encapsulation.
Here are two advantages of getter/setter methods vs public fields:
When setting a value through a setter method you can check and reject invalid values whereas if a field is public you can't control what values are assigned to it.
You don't need to provide a setter and getter method, giving you the possibility to make a field effectively read-only or write-only.
Changing it with methods give you more control on the logic you want to apply to access your member variables.
For example if a member variable is a readonly variable, you can omit the implementation of set method so nobody can write to the content.
Or on the other hand if you want to just write to a variable and don't want anybody read it later you can just implement set methods.
One other thing that setters will provide you is that you can have a validation before committing the value. For example if you expect a string of a certain format to be set to a member string variable, you can check it in the setter function and accept it if it matches the pattern or reject it if it doesn't.
It is generally the best practice to change/read the member variables through getters and setters
As a general rule of thumb, you want to be as restrictive as possible on your class properties and extension points (private > protected > public). This is particularly important in projects that run for a long period of time and need maintenance and re-factoring.
It's quite difficult to restrict your properties from public to protected/private once they have been used for a while, because you don't know how many other classes are relying on those properties being public. On the other hand, relaxing from private to protected/public is less traumatic because you don't have to worry about previous access to that property from without that class.
Having said that, getters and setters provide you with unique points of contact to interact with private members of a class. That's called encapsulation in OOP. That means that you can ensure that everyone that interacts with those properties are doing it in the same and consistent manner. A silly example would be normalization of the property:
private String name;
public void setName(String name) {
this.name = StringUtils.capitalize(name);
}
You're ensuring here that whoever sets a name does not need to care about its capitalization, because you're enforcing it through the setter. Same could apply to a getter, applying business rules as needed.
Compare that with accessing a public property which you then need to capitalize on your end every time you use it...
Finally, I'd say that blindly adding getters and setters to your objects is a bad practice. Only provide those accessors when there's a good reason for them to exist. For instance:
class Person {
private name;
public Person(String name) {
this.name = name
}
public String name() {
return name;
}
}
You normally don't set the name to a person, so we can omit that setter all together. But every person has a name. That being the case, you can enforce it via its constructor. This makes that distinction explicit, enhancing your design and preventing your object from being in a non-consistent state.
Read this forum post . You may find lot of valuable points to get understand the concepts.
http://www.cplusplus.com/forum/lounge/101305/
Following example class of getters and setters shows few good practices. We need to use const type qualifier etc. Also we can validate the values inside the implementation.
Eg:-
class ClassName{
string name;
int age;
int weight;
public:
void setName(string strName);
void setAge(int iAge);
void setWeight(int iWeight);
string getName() const { return name; }
int getAge() const { return age; }
int getWeight() const { return weight; }
};
I can summarize following good reasons of using accessors :
Making future changes easier
Encapsulation of behaviors with property
Insulating your public interface from change
Set different access levels
Validate values prior to setting or getting
Some java classes need to have private properties with a public getter and setter in order to function properly. For example JSF beans and JPA entities need them. If it wasn't for those libraries, there are probably some properties which should not have any getters and definitely not setters. Also empty constructors are oftenly discouraged for use by custom code. For example
#Entity
public class MyEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
public MyEntity() {}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
}
In this class the method setId should never be called by manual code. The method is not deprecated though, so an #Deprecated annotation would be wrong.
Is there another way than #Deprecated to tell a method should not be used?
JPA entities don't need public getters and setters. Values are set using reflection (at least when using EclipseLink or Hibernate which you're probably using).
In this particular example you could simply leave the setter out, I have made a habit out of it and never had a problem with it. Note: Stick to Java naming conventions when it comes to properties and getters/setters. Some libraries/frameworks (wrongly imo) depend on this.
As for the global concept of the question, I am surprised I didn't see a suggestion that includes documentation. Documentation has, is, and will probably always be your greatest communication to users of your code.
/**
* WARNING! DO NOT USE THIS UNLESS YOU ARE GOD!
* This will probably break stuff unless...
* ....
*/
public void doEvilHackishThings()
{
// Stuff happens here.
}
If you document your code properly, developers know when they're likely to break stuff. Make sure you don't apply voodoo code etc. Good documentation describes in some detail what it does and how it does it. No developer in his right mind will touch the example method without understanding why it is evil.
You could hide getters and setters by using an interface that is backed by that concrete class. This would also encourage Tell, don't ask, because there aren't any getters you could use on the interface. The constructor usage can also be hidden in factories.
I have a model object that's in fact an enum with fields and getters:
#Entity
public enum Type {
TYPE1, TYPE2, TYPE3, TYPE4;
#Column
private Long id;
#Column
private String name;
...
public String getName() {
return this.name;
}
...
}
It compiles and runs fine. However, if I call a getter method, it returns null (it doesn't load any values stored in the database). Is this the standard behavior? Is there a way to make JPA load them?
I'd say there is some misconception in this aproach:
Entities represent objects that can be stored in the database. In this case, the database (or any other persistent store) defines which instances are available.
Enums represent a fixed set of constants that are defined in source code. Thus the class itself defines which constants are available. In addition, it's generally bad practice to change the values of an enum, i.e. the name or id in your case.
You see that they are two quite different concepts which should be treated differently.
To store enums in entities (where the enum is a field of that entity), you could either use #Enumerated and store the name or ordinal of the enum, or (what we do more often) store one of the fields (we mostly use the id) and provide conversion methods.
If you want to store configurable "constants" in the database you might try and use plain entities for that, make the constructor private (Hibernate and other JPA providers should be able to deal with that) and provide an alternative implementation of the Enum class (you can't use the enum keyword though).
Have you looked into the #Enumerated annotation? I haven't ever tried to use it within an enum itself, however it works quit well binding a class property to an enum.
enum Type{TYPE1, TYPE2}
#Column(name="type")
#Enumerated(EnumType.STRING)
public Type getType(){return type;}
public void setType(Type t){type = t;}
If JPA cannot be made to handle this, you could add a public Type valueOf(long id) method to your enum class which you use as a factory to instantiate enum instances representing the values in your legacy table.