My initial venture in writing code started in 2010 with the Groovy scripting language. From there I went into a variety of other high level languages, and ended up getting into lower level languages (like C and Java) in 2018.
When I first wrote code, I had no idea of encapsulation. In Groovy, everything is public. There’s no idea of private fields or methods. At least, not in the way they would be represented in C++ or Java.
Take this example below (taken from Stack Overflow):
public class Person {
private String name
}
def u = new Person(name:"Ron")
println u.name
In Java this isn’t runnable. Trying to define a private field would keep the field from outside the Class itself. However, in Groovy this is perfectly fine. The code above in Groovy will output “Ron.”
As in another Stack Overflow question, private methods are also accessible:
class A {
private def sayHello() {
println "Anish"
}
}
def a_obj = new A()
a_obj.sayHello()
Some argue that Groovy adds Getters and Setters under the hood, so that private field was automatically given a hidden getter. By calling it, you are calling the getter. By changing the assignment, you (perhaps unknowingly) invoking the Setter.
While there may be a hidden setter method being invoked, it isn’t clear in the reading of the code itself. What if name, shouldn’t be modified outside the class?
Encapsulation
The idea behind encapsulation is that some methods or fields/variables are private. Their assignment is done through their Class methods. Outside the class, you either have to invoke a method to change the item. This enforces a control of flow.
Flow as in the development flow.
Throughout an application, different developers could change an assignment to an object. It might not be clear that this is happening because there’s no obvious flow (i.e. you’re not writing out a getter and setter and using that in place of direct access to the object.
If the language creates getters/setters (without you knowing), how do you keep an object from being modified if you only want it controlled by one method? Instead of invoking the one method to change the value, different developers could instantiate the Class and modify values outside the class in ways not intended.
public class Building {
private int walls;
private int height;
private int squareFeet;
private int numberOfDoors;
private boolean skylight;
private String flooringMaterial;
public Building(int walls, int height, int squareFeet, int numberOfDoors, boolean skylight, String flooringMaterial) {
this.walls = walls;
this.height = height;
this.squareFeet = squareFeet;
this.numberOfDoors = numberOfDoors;
this.skylight = skylight;
this.flooringMaterial = flooringMaterial;
}
public int getPrice(int listingNumber){
if(listingNumber == 1){
int price = 890000;
System.out.println("Condo #1 is selling at " + price);
return price;
}
return 0;
}
public int getWalls() {
return walls;
}
public void setWalls(int walls) {
this.walls = walls;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getSquareFeet() {
return squareFeet;
}
public void setSquareFeet(int squareFeet) {
this.squareFeet = squareFeet;
}
public int getNumberOfDoors() {
return numberOfDoors;
}
public void setNumberOfDoors(int numberOfDoors) {
this.numberOfDoors = numberOfDoors;
}
public boolean isSkylight() {
return skylight;
}
public void setSkylight(boolean skylight) {
this.skylight = skylight;
}
public String getFlooringMaterial() {
return flooringMaterial;
}
public void setFlooringMaterial(String flooringMaterial) {
this.flooringMaterial = flooringMaterial;
}
}
The Java code example above has set 6 fields, each as private. This locks my code into a flow – a flow of using specific methods to GET or SET changes to this object.
If we instantiate this class like so:
Building building = new Building(8, 68, 6500, 8, false, "concrete");
We can’t access the fields directly. That is, I can’t do:
building.walls = 5;
In Java, that will create an error – “walls has private access in Building.”
The developer is required to use an access method, like so:
building.setWalls(5);
We can check that with:
System.out.println(building.getWalls());
Sure enough the walls changed from the original value of 8, to the new value of 5.
Why Use Encapsulation?
It’s an honest question. Why use it? What gain is there?
When I look at Groovy code, or poorly written Ruby code (where everything is global) or JavaScript code, it feels so loose. By allowing anyone to change any field or kick off any method anywhere in the project it makes it hard for me to conceptualize control. There is no control.
I did throw JavaScript under the bus… I should clarify. JavaScript CAN use encapsulation, but it requires work on the part of the developer. It also doesn’t look clean IMO. In languages like C++ or Java, the private or public nature of the fields are defined at the top of the Class. It’s clear what is private and what will need getters and setters to access.
JavaScript requires one to use the Scope to control access, rather than notation. One doesn’t write “private int age;” in JavaScript… instead a function is defined and within that function is the age value. Access to that function controls how the field is assigned. It’s messy. You have to read the entire JavaScript file to get an idea of what methods are setting what variables to private, based on the scope of where the variable is defined.
Examples like JavaScript encapsulation leave me scratching my head as to what the hell is private or not.
Security
While JavaScript might be messy, variable scope is one way to keep a variable from getting accessed by anyone. So there is a work around, although IMO it’s quite messy and convoluted.
Another aspect of encapsulation is security. Take the Groovy example (or someone using Ruby or Java with all public fields and methods) and consider a project that has account information. If that project is compiled and treated as a library, whomever imports that compiled library, will have access to read and write to those same private fields. Hence the problem.
No responses yet