Implementing getters and setters in real life applications - Using OOPS
Introduction
Getters and Setters are one of the most underrated concepts of OOPs. We can use it in our applications to make the logic as well as code readability more clear and also we can make the workflow of the design patterns more verbose. I used this property for building a production grade backend. So you can use this as a reference. Moreover if python is your language then it will be definitely a turning point of your codebase.
But before moving to the concept of getters and setters we need to understand what is contructor of a class. The codes are written in python but the logic can be applied to any programming language.
Prerequisite - Basic knowledge of OOPs like what is a class , an object and how the initialization occurs, encapsulation and abstraction. That's it . This much easy the topic is going to be.
Constructor
A constructor is a function rather a special method that is called while we initialize an object of that particular class.
Here all the properties get binded to the object. In python, we access them using the
self
keyword and in JavaScript usingthis
keyword.So, it basically constructs the object by adding properties to it.
In python __init__
, a dunder method is the constructor function.
class Human:
# constructor
def __init__(self,legs,hands):
self.legs = legs
self.hands = hands
normal_human = Human(4,2)
print(normal_human.legs,normal_human.hands)
So we can see how it's all done. Now suppose we want to assign a property which is dependent on another property.
class Human:
# constructor
def __init__(self,legs):
self.legs = legs
self.hands = self.legs//2; # making the hands dependent on legs
normal_human = Human(4)
print(normal_human.legs,normal_human.hands) # 4,2
# legs changed but hands not changed ๐
normal_human.legs = 5
print(normal_human.legs,normal_human.hands) # 5,2
So now we can see the legs and hands are dependent but making changes in the legs not changing the hands. Here all the chaos occurs.
Possible Solution using methods
What can be a possible solution?? Well we can build a method which will calculate the value then return the modified value.
class Human:
# constructor
def __init__(self,legs):
self.legs = legs
def hands(self):
return self.legs//2;
normal_human = Human(4)
print(normal_human.legs,normal_human.hands()) # 4,2
normal_human.legs = 6
print(normal_human.legs,normal_human.hands()) # 6,3
It is running fine. But what if we want to make this simpler? Calling methods is not an ideal case every time.
Well here only the concept of the getters and setters. Using methods as attributes or variable or properties.
Getters
Methods for accessing an attribute and getting used as an attribute is called getter. So instead of making a public attribute , we will make a private attribute first so that it is not accessible directly even by the instances or objects.
Then we will use property decorator to make it a getter.
class Human:
# constructor
def __init__(self,legs):
self.legs = legs
self.__hands = 0
@property
def hands(self):
return self.legs//2;
# simpler code โ
normal_human = Human(4)
print(normal_human.legs,normal_human.hands) # 4,2
normal_human.legs = 6
print(normal_human.legs,normal_human.hands) # 6,3
Setters
Now what if we want to set the hand explicitly. Methods for setting or updating an attribute and getting used as an attribute is called setter.
class Human:
# constructor
def __init__(self,legs):
self.legs = legs
self.__hands = 0
@property
def hands(self):
return self.legs//2;
@hands.setter
def hands(self,value):
self.___hands = value
# simpler code โ
normal_human = Human(4)
print(normal_human.legs,normal_human.hands) # 4,2
normal_human.hands = 5
print(normal_human.legs,normal_human.hands) # 6,5
Using getters and setters with sqlalchemy ORM to store hashed password easily
What if instead of legs and hands we have a password property which should be actually a hashed value of the provided password?
Normally We do this using two properties which is unnecessary. Lets simplify it.
class Doctor(db.Model):
id = db.Column(db.Integer,primary_key = True)
name = db.Column(db.String(30),nullable=False)
__password = db.Column(db.String)
@property
def password(self):
return self.__password
@password.setter
def password(self,value):
self.__password = generate_password_hash(value)
Now technically you built a class which accepts password and only shows you the hashed password. Even changing password will lead to storing of hashed password.
Conclusion
Sometimes without using these concepts it is hard to visualise what the codebase actually wants to do. Yes I know functional oriented programming is a go and generally used by popular tech stacks but if you want to structure you code and secure it then OOP is the only key.