You are viewing a free preview of this lesson.
Subscribe to unlock all 10 lessons in this course and every other course on LearningBro.
This lesson covers encapsulation -- one of the four pillars of Object-Oriented Programming -- and the use of access modifiers to control visibility of class members. This is a core topic in the OCR A-Level Computer Science (H446) specification.
Encapsulation is the principle of bundling data (attributes) and the methods that operate on that data into a single unit (a class), while restricting direct access to the object's internal state. External code interacts with the object only through its public interface (methods), not by directly reading or modifying its attributes.
| Benefit | Explanation |
|---|---|
| Data protection | Private attributes cannot be accidentally modified by external code. |
| Controlled access | Getters and setters allow validation before data is read or changed. |
| Reduced coupling | External code depends on the public interface, not the internal implementation. |
| Easier maintenance | Internal implementation can change without affecting code that uses the class. |
| Easier debugging | Bugs related to data can be traced to the class itself. |
Exam Tip: Encapsulation is not just about making attributes private. The key benefit is controlled access -- you can validate data, enforce business rules, and change the internal implementation without breaking external code. Always explain these benefits, not just the definition.
Access modifiers (also called visibility modifiers) control which parts of a program can access an attribute or method.
| Modifier | Symbol (UML) | Accessible From | Python Convention |
|---|---|---|---|
| Public | + | Anywhere -- inside and outside the class | self.name |
| Private | - | Only inside the class itself | self.__name |
| Protected | # | Inside the class and its subclasses | self._name |
Python does not enforce access modifiers at the language level. Instead, it uses naming conventions:
class Employee:
def __init__(self, name: str, salary: float, department: str):
self.name = name # Public
self._department = department # Protected (convention)
self.__salary = salary # Private (name mangling)
self.name): Accessible from anywhere.self._department): Intended for internal use and subclasses. Not enforced.self.__salary): Python applies name mangling -- the attribute is renamed to _Employee__salary internally, making accidental access difficult.| Modifier | Same Class | Same Package | Subclass | Everywhere |
|---|---|---|---|---|
public | Yes | Yes | Yes | Yes |
protected | Yes | Yes | Yes | No |
| (default/package) | Yes | Yes | No | No |
private | Yes | No | No | No |
Getters (accessor methods) and setters (mutator methods) provide controlled access to private attributes. They form the public interface through which external code interacts with the object's data.
class Person:
def __init__(self, name: str, age: int):
self.__name = name
self.__age = age
def get_name(self) -> str:
return self.__name
def get_age(self) -> int:
return self.__age
def set_name(self, name: str):
self.__name = name
def set_age(self, age: int):
self.__age = age
class Person:
def __init__(self, name: str, age: int):
self.__name = name
self.set_age(age) # Use setter for validation
def get_name(self) -> str:
return self.__name
def get_age(self) -> int:
return self.__age
def set_name(self, name: str):
if not name.strip():
raise ValueError("Name cannot be empty")
self.__name = name.strip()
def set_age(self, age: int):
if not isinstance(age, int):
raise TypeError("Age must be an integer")
if age < 0 or age > 150:
raise ValueError("Age must be between 0 and 150")
self.__age = age
Subscribe to continue reading
Get full access to this lesson and all 10 lessons in this course.