What is the difference between public, private, and protected?
Difference Between public
, private
, and protected
Access Modifiers
In object-oriented programming (OOP), access modifiers like public
, private
, and protected
control the visibility and accessibility of class members (attributes and methods). These modifiers help enforce encapsulation, one of the core principles of OOP, by restricting direct access to an object's internal state and ensuring that it can only be modified in controlled ways.
Access Modifiers Overview
- Public
- Private
- Protected
Detailed Explanation
1. Public
- Definition: Public members are accessible from anywhere in the program. They can be accessed by any other class or function that has a reference to the object.
- Usage: Used for methods and attributes that need to be accessible from outside the class, serving as the interface for interaction with the object.
Example in C++:
class Car { public: std::string model; // Public attribute void drive() { // Public method // Driving logic } };
Example in Python:
In Python, all members are public by default.
class Car: def __init__(self, model): self.model = model # Public attribute def drive(self): # Public method print("Driving")
2. Private
- Definition: Private members are accessible only within the class they are declared. They cannot be accessed or modified directly from outside the class.
- Usage: Used to hide internal implementation details and protect the integrity of the object's state.
Example in C++:
class Car { private: int speed; // Private attribute void accelerate() { // Private method speed += 10; } public: void setSpeed(int s) { if(s >= 0) speed = s; } int getSpeed() const { return speed; } };
Example in Python:
Python does not have true private members, but uses name mangling to indicate privacy.
class Car: def __init__(self, model): self.__speed = 0 # Private attribute (name mangled) def accelerate(self): self.__speed += 10 def get_speed(self): return self.__speed
Accessing __speed
from outside the class would raise an AttributeError:
car = Car("Toyota") print(car.__speed) # AttributeError
But it can still be accessed via name mangling:
print(car._Car__speed) # Output: 0
3. Protected
- Definition: Protected members are accessible within the class they are declared and by derived (subclass) classes. They are not accessible from outside the class hierarchy.
- Usage: Used to allow subclasses to access and modify certain members of the parent class while keeping them hidden from other parts of the program.
Example in C++:
class Vehicle { protected: int speed; // Protected attribute public: void setSpeed(int s) { speed = s; } }; class Car : public Vehicle { public: void displaySpeed() { std::cout << "Speed: " << speed << std::endl; // Accessible here } };
Example in Python:
Python uses a single underscore to indicate protected members by convention.
class Vehicle: def __init__(self): self._speed = 0 # Protected attribute class Car(Vehicle): def display_speed(self): print(f"Speed: {self._speed}") # Accessible in subclass
Accessing _speed
from outside the class hierarchy is discouraged but technically possible.
Summary of Access Levels
Modifier | Accessible Within Class | Accessible in Subclasses | Accessible Outside Classes |
---|---|---|---|
Public | Yes | Yes | Yes |
Protected | Yes | Yes | No |
Private | Yes | No | No |
Purpose and Benefits
- Encapsulation: By controlling access to class members, encapsulation hides the internal state and implementation details, exposing only what is necessary.
- Maintainability: Reduces dependencies between different parts of the code, making it easier to modify and maintain.
- Security: Protects the integrity of the object's state by preventing unauthorized or unintended modifications.
- Clarity: Clearly defines the interface and implementation boundaries, making the code more understandable.
When to Use Each Modifier
- Public: Use for methods and attributes that are intended to be part of the class's interface and need to be accessible from outside the class.
- Protected: Use for members that should be accessible within the class and its subclasses but not from outside the class hierarchy.
- Private: Use for members that should be completely hidden from outside access, ensuring that they can only be modified internally within the class.
Additional Considerations
- Python's Philosophy: Python emphasizes "we are all consenting adults here," meaning that access modifiers are more about conventions than strict enforcement. Developers are expected to respect these conventions.
- C++ and Java: These languages enforce access modifiers strictly, providing stronger encapsulation and access control.
Practical Example in C++
#include <iostream> #include <string> class Person { private: std::string name; // Private attribute protected: int age; // Protected attribute public: Person(std::string n, int a) : name(n), age(a) {} void setName(std::string n) { name = n; } std::string getName() const { return name; } void displayInfo() const { std::cout << "Name: " << name << ", Age: " << age << std::endl; } }; class Employee : public Person { public: Employee(std::string n, int a) : Person(n, a) {} void promote() { age += 1; // Accessing protected member } }; int main() { Employee emp("Alice", 30); emp.displayInfo(); // Name: Alice, Age: 30 emp.promote(); emp.displayInfo(); // Name: Alice, Age: 31 // emp.age = 35; // Error: 'age' is protected // emp.name = "Bob"; // Error: 'name' is private return 0; }
Practical Example in Python
class Person: def __init__(self, name, age): self.__name = name # Private attribute self._age = age # Protected attribute def set_name(self, name): self.__name = name def get_name(self): return self.__name def display_info(self): print(f"Name: {self.__name}, Age: {self._age}") class Employee(Person): def promote(self): self._age += 1 def display_info(self): super().display_info() if __name__ == "__main__": emp = Employee("Alice", 30) emp.display_info() # Name: Alice, Age: 30 emp.promote() emp.display_info() # Name: Alice, Age: 31 # print(emp.__name) # AttributeError print(emp._age) # 31 (accessible but discouraged)
Conclusion
Understanding and appropriately using access modifiers like public
, private
, and protected
is fundamental to writing clean, maintainable, and secure object-oriented code. These modifiers help enforce encapsulation, ensuring that the internal state of objects is protected and that classes expose only the necessary interfaces for interaction.
By adhering to best practices around access control, you can create more robust and well-structured codebases that are easier to understand, maintain, and extend.
Happy Coding!
GET YOUR FREE
Coding Questions Catalog