What is the difference between public, private, and protected?

Free Coding Questions Catalog
Boost your coding skills with our essential coding questions catalog. Take a step towards a better tech career now!

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

  1. Public
  2. Private
  3. 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

ModifierAccessible Within ClassAccessible in SubclassesAccessible Outside Classes
PublicYesYesYes
ProtectedYesYesNo
PrivateYesNoNo

Purpose and Benefits

  1. Encapsulation: By controlling access to class members, encapsulation hides the internal state and implementation details, exposing only what is necessary.
  2. Maintainability: Reduces dependencies between different parts of the code, making it easier to modify and maintain.
  3. Security: Protects the integrity of the object's state by preventing unauthorized or unintended modifications.
  4. 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!

TAGS
Coding Interview
CONTRIBUTOR
Design Gurus Team

GET YOUR FREE

Coding Questions Catalog

Design Gurus Newsletter - Latest from our Blog
Boost your coding skills with our essential coding questions catalog.
Take a step towards a better tech career now!
Explore Answers
Does Apple ask system design questions?
What is a hybrid job?
Is it easy to get into Uber?
Related Courses
Image
Grokking the Coding Interview: Patterns for Coding Questions
Grokking the Coding Interview Patterns in Java, Python, JS, C++, C#, and Go. The most comprehensive course with 476 Lessons.
Image
Grokking Data Structures & Algorithms for Coding Interviews
Unlock Coding Interview Success: Dive Deep into Data Structures and Algorithms.
Image
Grokking Advanced Coding Patterns for Interviews
Master advanced coding patterns for interviews: Unlock the key to acing MAANG-level coding questions.
Image
One-Stop Portal For Tech Interviews.
Copyright © 2024 Designgurus, Inc. All rights reserved.