According to the OOP concepts, encapsulation is considered as defined private variables and public getter and setter methods.
Example:
public class Student {
private String name;
private int id;
public void setName(String name){
name = this.name;
}
public void setID(int Id){
id= this.id;
}
public String getName(){
return name;
}
public int getID(){
return id;
}
}
But if I wrote this code in the following way, could I say this class follows encapsulation concept ?
Because here, we return department name by using public method.
public class Student {
private department;
public String getDepartmentOfStudent(String name){
// write java code to get department name based on name from DB
return department;
}
}
Case II: If private variable department was not declared and just return value retrieved from DB, would we say that this class follows encapsulation?
But if I wrote this code in the following way, could I say this class follows encapsulation concept ?. Because here, we return department name by using public method.
=> Usually getter and setter are public. variables are private.
Case II : If private variable "department" was not declared and just return value retrieved from DB, would we say that this class follows encapsulation?.
=> Yes, its still encapsulation . It is not mandatory to have both getter and setter for every variable. So how you set data in variable, does not matter.
Encapsulation is defined as the wrapping up of data under a single
unit. It is the mechanism that binds together code and the data it
manipulates.Other way to think about encapsulation is, it is a
protective shield that prevents the data from being accessed by the
code outside this shield.
1 - Technically in encapsulation, the variables or data of a class is
hidden from any other class and can be accessed only through any
member function of own class in which they are declared.
2 - As in encapsulation, the data in a class is hidden from other classes, so it is also known as data-hiding.
3 - Encapsulation can be achieved by: Declaring all the variables in the class as private and writing public methods in the class to set
and get the values of variables.
Source:- https://www.geeksforgeeks.org/encapsulation-in-java/
For both cases, the answer is also "Yes". It is because your private field variable is not being accessed directly by other classes (e.g. declaring it as public String department). Accessible department is still being controlled by the code path of public String getDepartmentOfStudent(String name) which is playing the role of a public getter.
Getter gets it's names due to it's functionality that it returns some private attributes not by it's name. For example: getName() or getAge().
If a method named abc() returns some private data member/attribute then it is a getter method.
Yes your code follows encapsulation. In encapsulation the variables of the object cannot be directly accessed and modified by any other object.
In Case II:
If private variable "department" was not declared and there is no other public variables in your class, then yes you have encapsulation as the class's variables or data cannot directly accessed by another class.
To answer both questions we need take into account the concept of encapsulation
The localization of knowledge within a module. Because objects
encapsulate data and implementation, the user of an object can view
the object as a black box that provides services. Instance variables
and methods can be added, deleted, or changed, but as long as the
services provided by the object remain the same, code that uses the
object can continue to use it without being rewritten. (...)
So, we can say YES, it does; because to the client consuming the information provided by Student there is no knowledge of how the value of department is being retrieved/handled and returned, it just knows that from the call to getDepartmentOfStudent will be a String result. It actually doesn't care whether it is comming from database or memory, only Student knows that.
Related
I'm trying to create a snacks machine implementation in java.
I have created an abstract class named Product that will give the basic design for each of the offered products.
I mean we have the abstract class Product and then other classes like Nachos, Cake, etc.. that inherita from Product.
Product class does not contain too much, it just contains the name , the price and the available amount of the product (these are the fields in the class).
It also has get methods for the fields that just return the value for each one.
The problem is that I want to set the name of the product as a static final because if a product's name is Nachos, it won't be changed. I mean it'll be possible to create more Nachos objects but the name of their class is still going to be Nachos.
So there is no reason to NOT to do that static final.
The issue with that is that i'm not sure how to set it correctly.
public abstract class Product {
private static final String productName = getClass().getSimpleName();
private int price;
private int amount;
....
Constructor..
Get methods..
I thought about getClass().getName() or getSimpleName() but it gives me an IDE error which indicates that the only way for me to also use that field as static final and also to use getClass is by writing Product.class.getName();.
The problem is that if i'll do that, the name that will be returned is Product and not Cake or Nachos or other sub classes.
If your Class has some attribute that describes that Class (e.g a product name), that's an attribute of that Class. You shouldn't write code that uses the name of the class itself with getClass().getName(), that's tying your business logic to implementation details, and there's no reason (or very few good reasons), why your code would need to know the name of the class itself.
Instead, add an attribute like productName to your class:
public class Product{
private String productName;
public Product(String name){
this.productName = name;
}
public String getProductName(){
return this.productName;
}
}
You should just use "final" and drop the "static". By declaring the variable as final you can assign the value of "getClass" that use "this" for reference. "this" doesn't work for static.
abstract class Product {
private final String productName = this.getClass().getSimpleName();
public String getProductName() {
return productName;
}
}
The "this" can be omitted in "this.getClass().getSimpleName()", leaving only "getClass().getSimpleName().
It doesn't make sense to use "static" because you would access the attribute directly via the class reference. But this would not work because to get the "getClass" you would need to be within some scope (constructor...) because the attribute is static, it is impossible to assign the value of the attribute at the time of its creation, making it impossible to use the " Final".
A static member belongs to the class in which it is defined. Declaring productName as static on the class Product means that every concrete implementation would have the same value. This is not what you want.
I think the solution that is closest to what you describe is not to have a member at all. Instead, declare an accessor as follows.
public abstract class Product {
public final String getProductName() {
return getClass().getSimpleName();
}
}
Thus, every instance of a given subclass (e.g. Taco) references the same Class object for its type. We never duplicate the value because we are accessing the singular value in our memory space. We declare this method to be final so that subclasses cannot override it. This enforces that the productName will always be the simpleName of the concrete implementation.
The below class doesn't have final keyword but its member variables are private and final and the class exposes no mutate/set methods. Is this class immutable or not?
public class Abc {
private final int id;
private final String name;
public Abc(int id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
}
The class itself is immutable, yes - if you create an instance of just Abc, no aspect of that can be changed after the instance has been created.
However, that doesn't mean that any code receiving a parameter of type Abc can assume it's immutable with all the benefits that carries... because the class isn't final. It's entirely possible for an object of a type compatible with Abc to be mutable:
public class Mutable extends Abc {
private String value;
public Mutable(int id, String name) {
super(id, name);
}
public void setValue(String value) {
this.value = value;
}
#Override public String toString() {
return value;
}
}
Now imagine you've got code which deals with an Abc:
public class AbcConsumer {
private final Abc abc;
public AbcConsumer(Abc abc) {
this.abc = abc;
}
// No need to create a defensive copy or anything like that...
// abc is immutable, right?
public Abc getAbc() {
return abc;
}
}
Here the consumer assumes it's fine to treat Abc as if it's an immutable class - but if someone creates an AbcConsumer by passing in a Mutable instance instead of "vanilla" Abc instance, it could cause problems.
That's why it's generally a good idea when you're creating an immutable type to make it final as well - that way any consumers know that if they receive a reference with that type, it's definitely immutable.
To put it another way: yes, the Abc class is immutable... but you can't assume that a reference with a compile-time type of Abc refers to an immutable object.
As presented, yes, the class is immutable.
The "final" keyword on a class declaration prevents it from being extended - it's not related to immutability (unless your variables are declared public or protected).
Edit; "not related" is a poor choice of words, please see Jon Skeet's answer below
No, it is most likely not.
A problem is terminology. What do you mean by class? If you mean this code, sure, it's immutable. But 'this code' is not something that is particularly relevant to the concept of immutability. That usually makes a lot more sense if we consider it: this type.
As in, is the type Abc immutable?
As in, given:
public void foo(Abc abc) { ... }
is it safe to assume that the received abc couldn't possibly change?
And then the answer is no. That is not safe to assume: The type Abc is mutable.
The reason is that someone could make this:
class SneakyAbc extends Abc {
private int id;
public void setId(int id) {
this.id = id;
}
public String getId() {
return id;
}
}
This is why immutable classes are virtually always made final, to fully guarantee it.
Depending on how fancy you want to paint with the brush of 'what does this term mean', if all methods of Abc are final, you can consider it immutable as well if you really want to: Whilst the class does not need to be immutable (a subclass can add a new non-final field and create getters and setters for this), all the stuff you can 'witness' from the Abc type, assuming you don't use reflection, do appear immutable.
Exactly what definition of immutable you go with would be required knowledge to delve any further.
Note that something like java.io.File has only final fields and is final, and yet, it has easily observable state that can be modified: just.. delete the file, and voila you can see it. You can pull similar stunts with an IdentityHashMap to create a faux but nevertheless very observable 'field'.
Thus, 'immutable' as a concept: Useful. As a boolean flag to bestow upon a certain type or some java source file: Not useful.
Records
Other Answers directly addressed your questions about immutability, class being marked final, and subclasses being mutable. I’ll add an alternative option to more briefly accomplish your goal of immutability: Records.
Java 16 brings the new records feature. If the main purpose of your class is to immutably and transparently carry data, define your class as a record. The compiler implicitly creates default constructor, getters, equals & hashCode, and toString.
A record is implicitly final, so no risk of a subclass becoming mutable.
Declare the properties in parentheses. By default, you need not put anything in the curly braces body of a record.
record Abc ( int id , String name ) {}
Instantiate like any other class.
Abc x = new Abc ( 42 , "Snuffleupagus" ) ;
The implicit getter methods are simply the property names. The JavaBeans-style get…/is… method naming is not used. (You could add such methods if required.)
System.out.println( x.name() ) ;
Snuffleupagus
It is mutable if its internal states can be changed after the class is created.
In your example, although there is no class final, the inside situations cannot be changed again because of final keyword. In this way, the class becomes immutable again
We always say that, Encapsulation keeps data and functionality safe from the outside world.
So its a protective wrapper around the class and the code can be saved from unauthorized access by outer world.
But what if,
I declare one variable with public modifier will it break Encapsulation ?
Encapsulation in Java is a mechanism of wrapping the data (variables) and code acting on the data (methods) together as a single unit. In encapsulation, the variables of a class will be hidden from other classes, and can be accessed only through the methods of their current class. Therefore, it is also known as data hiding.
public class EncapTest {
private String name;
private String idNum;
private int age;
public int getAge() {
return age;
}
public String getName() {
return name;
}
public String getIdNum() {
return idNum;
}
public void setAge( int newAge) {
age = newAge;
}
public void setName(String newName) {
name = newName;
}
public void setIdNum( String newId) {
idNum = newId;
}
}
so that all your methods and variable should be private
In my idea modifiers absolutely supports Encapsulation. Maybe you just violate Information Hiding.
Encapsulation is not information hiding. Information hiding is a more fundamental technique than encapsulation. We should clarify between Encapsulation and Information Hiding. (see the reference)
Encapsulation is a technique for expressing the boundaries of
those modules.
Suppose that we have an attribute in our class and we need to set some values from external the class. We can not define it as public. We can not define it as protected too (see this question), the only way to define this types of conditions is defining some methods (or some modifiers in very simple interface). In this case we Encapsulate it.
So what is the difference between a public attribute and a private attribute with modifiers?
In a very big projects, we can add some other conditions to modifiers without any changes to other parts of project (the OCP of SOLID).
Finally: In some cases we need to set some values from outside the class to attributes. So sometimes we need to use modifiers and it is the encapsulation way to access the fields. We can not define the fields as public or protected in OOP.
First of all, let's see what encapsulation really is.
Encapsulation is one of the four OOP concepts.
In encapsulation, the variables of a class will be hidden from other classes, and can be accessed only through the methods of their current class. Therefore, it is also known as data hiding.
So making a class variable public it's not encapsulation anymore.
Let's see some real usages of encapsulation:
By encapsulating, you force yourself and other developers to access that variable through their getters and setters. Let's be honest, it's the same thing as if the field was public, right?
But what if you add some logic to the setters?
public class User {
private String username;
private String password;
// username getter and setter not displayed in this example.
public void setPassword(String password) {
this.password = someCoolHashingMethod(password);
}
public String getPassword() {
return this.password;
}
}
Do you see what's happening there? You force the password to be stored as a hash instead of clear. (There are many ways to protect a password but we'll stick to this dummy example for now).
Another real use for encapsulation is that you can change the name of the variable without changing the code everywhere in your application.
So you if you change it's name and it's not encapsulated, you will have to go everywhere you used it, modified it, to change there aswell. So a project level refactorization is needed. But if it's encapsulated, you used getters and setters everywhere! That means you just need to change it there only. Example:
public class User {
private String username;
private String pass; // <---- notice the new name
// username getter and setter not displayed in this example.
public void setPassword(String password) {
this.pass = someCoolHashingMethod(password); // <---- notice the new name
}
public String getPassword() {
return this.pass; // <---- notice the new name
}
}
Hope this answered a little bit more than your question really was.
This question already has answers here:
Immutable Type: public final fields vs. getter
(9 answers)
Closed 6 years ago.
Is it recommended to have public access modifiers for the data fields in final (Immutable) java class, even if the data fields are not the references to mutable datatype Or Shall we access data fields directly as data fields are supposed to be defined in constructor itself hence nullify all chances of changing the internal representation of class.
Please suggest?
For example:
public class MainApp {
public static void main(String args[]) {
Immutablesample immutablesample = Immutablesample.getInstance("akkhil");
System.out.println(" Before modification " + immutablesample.getName());
immutablesample.name = "gupta";
System.out.println(" After modification " + immutablesample.getName());
}
}
is the calling code trying to change the data field by accessing it directly(without access modifier) for the following class:
public final class Immutablesample {
private final String name;
private Immutablesample(String name){
this.name = name;
}
public String getName(){
return name;
}
public static Immutablesample getInstance(String name){
return new Immutablesample(name);
}
}
How would it make the class prone to get its internal representation changed if i change the modifier from private to public
private String name; to public String name;
since the object was creating with parameterized constructor so has immutable data fields, than why is it necessary to make data fields private?
Two simple rules to follow:
Try to make your whole class as "immutable" as you can. For example setting private final fields only via constructors. And when using "incoming" collection objects, consider to create a copy of their content to be really on the safe side.
Keep in mind that good OO is about exposing behavior; not about exposing data. Meaning: you absolutely do not want to make fields public unless you have really good reasons to do so. In other words: you do not want that some other class B does something because of the content of some field in class A. And the way to prevent that: making your fields private!
In general, it's a bad decision to show your inner presentation of a class, so it's much better if you hide even final immutable fields. You can only show such as fields if your class it's something like a tuple, where all members are used from outside.
I am still very confused about getter and setter methods. I had this code;
public class MethodsInstances {
public MethodsInstances(String name){
girlName = name;
}
private String girlName;
public String getName(){
return girlName;
}
public void sayName(){
System.out.printf("Your first gf was %s", getName());
}
}
But for "sayName", why couldnt you instead of using getName(), just type girlName? It would be the same, because getName() returns girlName, as seen in the code. Also, do the methods have to start with get and set, or can be named whatever you want?
Huge thanks from the newbie coder, Dan B
The point of getters and setters is that only they are meant to be used to access the private varialble, which they are getting or setting. This way you provide encapsulation and it will be much easier to refactor or modify your code later.
Imagine you use girlName instead of its getter. Then if you want to add something like a default (say the default name is 'Guest' if it wasn't set before), then you'll have to modify both the getter and the sayName function.
There is no requirement for getters and setter to start with get and set - they are just normal member functions. However it's a convention to do that. (especially if you use Java Beans)
You absolutely can use the variable directly in your example, mostly because sayName() is in the same class.
Other than that, I see 3 reasons for having getters and setters:
1.) It's a principle of object oriented programming to keep values (state) private and provide public methods for interaction with other classes.
2.) Classes with getters and setters often follow the Java beans design pattern. This pattern allows those objects to be used in template engines or expression languages like JSP or Spring.
3.) In some cases it prevents actual errors. An example:
public class DateHolder() {
public Date date;
public static void main(String... args) {
DateHolder holder = new DateHolder();
holder.date = new Date();
System.out.println("date in holder: "+holder.date);
Date outsideDateRef = holder.date;
outsideDateRef.setTime(1l);
//will be different, although we did not change anything in the holder object.
System.out.println("date in holder: "+holder.date);
}
}
wrapping the date variable with getter and setter that operate only with the value, not the reference, would prevent this:
public class DateHolder() {
private Date date;
public Date getDate() {
return (Date)this.date.clone();
}
public void setDate(Date date) {
this.date = (Date) date.clone();
}
public static void main(String... args) {
DateHolder holder = new DateHolder();
holder.setDate( new Date() );
System.out.println("date in holder: "+holder.getDate());
Date outsideDateRef = holder.getDate();
outsideDateRef.setTime(1l);
//Date in holder will not have changed
System.out.println("date in holder: "+holder.getDate());
}
}
You can use girlName here you really don't have to call getName(). The reason you need getName() is if you you want to get the name outside of this class. For example if you create a new class and then create the above class object in the new class and assign that object a name (value for girlName) you won't be able to access girlName from new class since it is private .. so you need a public method which will get the value for you.
Also it doesn't have to be getName or setName but this just makes it easy to understand what function is doing.
It's a common design patter to encapsulate the process of "getting" and "setting" variables in methods. This gives you more freedom if you ever want to change the underlying implementation.
For an example, lets say you one day want to change the parameter girlName to be an object Girl instead;
If you directly access girlName from your outer classes, you will have to change all your external code.
With a setter method, you could simply change one method and do
public void setGirlname(String name)
{
girlname = new Girl(name, some_other_data);
}
Or perhaps you want to make sure girlname always is returned with uppercase.
public String getGirlname()
{
return girlName.toUpperCase();
}
Thus giving you a loot more flexibility in your code design.
You must first read about abstraction, encapsulation and OOP to understand about accessors, mutators, immutability and data access.
We want to prevent direct access to the variable, we make the variable a private variable.
When the variable is private, other classes are not able to access that variable.
If we create variable as public it is accessible for all.
to change the actual private variable we will now need public getter() or setter().
The basic naming conventions say that we will take the name of the variable and prefix it with get and/or set.
in your specific case the getGirlname would be correct.
We call this encapsulation
This way you can inspect classes and invoke them at runtime using Reflection. See more here
HTH
Ivo Stoykov