DEV Community

Danyson
Danyson

Posted on • Updated on

Private variables are Private

We see, quite lot of us comfortable with getters and setters in objects, for accessing private variables.

But exposing a private variable with a getter or manipulate it with a setter, doesn't make any sense of why we made those variables private in the first place.

Instead we could have made them public, right ?

Consider the difference between 1a and 1b,

Example 1a : graph.ts

class Graph {
    _x = 0;
    _y = 0;

    get x():number{
        return this._x;
    }

    get x():number{
        return  this._y;
    }

    set x(x:number){
        this._x = x;
    }

    set y(y:number){
        this._y = y;
    }

}
Enter fullscreen mode Exit fullscreen mode

Example 1b : graph.ts

class Graph {
    getXYCoordinates(){
        // some code
    };

    setXYCoordinates(x: number, y:number){
        // some code
    };

    getXYZCoordinates(){
        // some code
    };

    setXYZCoordinates(x: number, y:number, z:number){
        // some code
    };
}
Enter fullscreen mode Exit fullscreen mode

As we see, both 1a and 1b tries to set x,y points in a cartesian plane.

Yet,

1a exposes its implementation.
1b hides its implementation.

Both has the features of a Data Structure. While 1b is even more, an Object.

You can't say which type of graph 1b is, it may be a 3D graph or a 2D graph.

And this is what we know as Abstraction.

Which means
Hiding the implementation

A class is not something that gets and sets the data rather it manipulates only the essence of the data, without the need to know its implementation.

We can't simply add more and more getters inside a class like the following journey.js

class Journey {
    getSpeedRange(){
        // some code
        };

    getKMTravelled(){
        // some code
        };

    getTotalTime(){
        // some code
        };
}
Enter fullscreen mode Exit fullscreen mode

If we do, then it is not hiding its implementation, rather its just exposes its variables through plenty of getters.

Rather we can,

class Journey {
    getAverageSpeedForTotalJourney(){
        // some code
        };
}
Enter fullscreen mode Exit fullscreen mode

We must know a way to represent the data that an object contains.

By hiding the implementation of the data and exposing only its behavior.

We make variables private so that we can hide their details to the outside World.

In objects, data holders are hidden in the name of Abstraction and the functions that work on those data are exposed.

If we are trying to expose the data, then we are not working with objects here.

We call them Data Structures

As Data Structures and Objects are Anti-Symmetry.

Data Structures are opposite to that of Objects.

In Data Structures, data holders are exposed and they have no meaningful functions to work on those data.

Lets see an example regarding Data Structures,

interface Square {
    side: number;
}

interface Rectangle{
    length: number;
    width: number;
}

interface Circle{
    radius: number;
}


class Geomentry {
    square: Square;
    rectangle: Rectangle;
    circle: Circle;

    constructor(square: Square, rectangle: Rectangle, circle: Circle){
        this.square = square; 
        this.rectangle = rectangle;
        this.circle = circle;
    }


    AreaOfSquare(): number{
        return this.square.side ** 2;
        }

    AreaOfRectangle(): number{
        return this.rectangle.length * this.rectangle.width;
        }
    AreaOfCircle(): number{
        const pi = 3.14285;
        return pi * this.circle.radius ** 2;
        }

}
const geomentry = new Geomentry({side: 6}, 
                                {length: 10, width: 5}, 
                                {radius: 6});

console.log("Area of Square", geomentry.AreaOfSquare());

console.log("Area of Rectangle", geomentry.AreaOfRectangle());

console.log("Area of circle", geomentry.AreaOfCircle());

[LOG]: "Area of Square",  36 
[LOG]: "Area of Rectangle",  50 
[LOG]: "Area of circle",  113.14285714296 
Enter fullscreen mode Exit fullscreen mode

The above implementation of finding the area of geomentrical shapes like square, rectangle and circle follows Procedural Programming not Object Oriented Programming, as our interfaces are used as Data structres which help us to model our data.

As the Data Structures of different shapes follow Procedural Programming, there is no need of hiding the implementation of data, thus there is no need of making variables private.

We can add more functions in our procedure, to work with our data.

Like we can add a function like sumOfAllSidesOfSquare() that can return total length of all the sides combined and lot more functions that can work on the defined Data Structure.

But adding new Data Structures is hard as the functions should also change.

But it's totaly opposite, when we do Object Oriented Programming.

Let's see an OOP example of the above,

interface Shape {
    areaOfSquare(): number;
    areaOfRectangle(): number;
    areaOfCircle(): number;
}

class Geomentry implements Shape {
    _square!: {side: number};
    _rectangle!: {length: number, width: number};
    _circle!: {radius: number};
    constructor(square: { side: number; }, 
                rectangle: { length: number; width: number; }, 
                circle: { radius: number; }) {
        this._square = square;
        this._rectangle = rectangle;
        this._circle = circle;
        }

    areaOfSquare(): number {
        return this._square.side ** 2;
        }

    areaOfRectangle(): number {
        return this._rectangle.length * this._rectangle.width;
        }

    areaOfCircle(): number {
        const pi = 3.14285;
        return pi * this._circle.radius ** 2;
        }

}

const geomentry = new Geomentry({side: 6}, 
                                {length: 10, width: 5}, 
                                {radius: 6});

console.log("Area of Square", geomentry.areaOfSquare());

console.log("Area of Rectangle", geomentry.areaOfRectangle());

console.log("Area of circle", geomentry.areaOfCircle());

[LOG]: "Area of Square",  36 
[LOG]: "Area of Rectangle",  50 
[LOG]: "Area of circle",  113.14285714296 
Enter fullscreen mode Exit fullscreen mode

The above implementation of finding the area of geomentrical shapes like square, rectangle and circle follows Object Oriented Programming, as our interface named Shape is implemented as an Object.

As the shapes follow Object Oriented Programming, there is a need of hiding the implementation of data, thus we made variables private for the purpose of Abstraction.

We can add more classes by implementing the interface in our OOP code.

But adding new Functions is hard as the Classes should also change.

Thus we come to a philosopy of,

In Procedural programming its hard to add new Data Structures as all the functions must change.

In Object Oriented Programming its hard to add new functions because all the classes must change.

In Software engineering, we don't need to represent everything as an Object.

Sometimes we need Functions that can work with Data Structures in a Procedural code.

There is no need of hiding the data thus no need of Private variables.

When we represent an Object, we need to hide the data.

Which paves the way for Private variables for the sake of Abstraction.

Thus there is no need to expose the Private variables with getters and setter unnecessarily.

Visit my Blog here!

Top comments (2)

Collapse
 
illusionelements profile image
IllusionElements

Why use _ when we have true private variables in classes with #variableName now
,,

Collapse
 
danyson profile image
Danyson

Yes, this is for example purpose to convey the message.