Community resourceWorksheet

OCR H446 1.2.4 Object Oriented Programming 2

Part 3 of 6 · H446 Data Structures and OOP

This worksheet explores the concept of encapsulation in object-oriented programming. Pupils work through examples and tasks involving private attributes, getter and setter methods, and validation logic to control changes to object data. The tasks require basic to moderate programming skills, focusing on designing safe and sensible class interfaces.

Shared by Chris H.Verified teacher

  • 12 cells
  • About 50 minutes
  • CC BY-SA 4.0
  • Shared 29 Jul 2026

Preview

The whole resource, exactly as a class sees it. Answers and marking are held back.

Encapsulation and class interfaces

OCR H446 references: 1.2.4(e) and 2.2.1(f)

Objects often store values that must remain sensible. A game character's health should not accidentally become greater than its permitted maximum, a laboratory sensor should reject an impossible calibration value, and a ticketing account should not allow an invalid balance change.

Encapsulation gives the class responsibility for protecting its own data. Other parts of the program use a clear public interface instead of changing sensitive values directly.

By the end, you should be able to:

  • distinguish public and private members
  • explain why controlled access protects an object's valid state
  • identify getter functions and setter procedures
  • implement simple validation through a class interface

Why control access to an object's data?

Consider a fitness-tracking app with an object that stores a user's daily step goal. If any part of the program can replace that value directly, a mistake could set it to -5000 or even to text. The object would then contain a value that makes no sense.

Encapsulation addresses this by placing the data and the methods that control it inside the same class.

Public and private members

A public member is part of the class interface: code outside the class is expected to use it.

A private member is intended for use only inside the class. Outside code should request access through public methods.

The public interface acts as a controlled doorway. It can:

  • return a stored value without exposing how it is represented
  • check a requested change before accepting it
  • reject a value that would leave the object in an invalid state

Getters and setters

A getter, also called an accessor, returns a stored value. It normally reads the object's state without changing it.

A setter, also called a mutator, requests a change. A well-designed setter can validate the new value before storing it.

OCR pseudocode

class ExamResult
    private mark

    public procedure new(startMark)
        mark = startMark
    endprocedure

    public function getMark()
        return mark
    endfunction

    public procedure setMark(newMark)
        if newMark >= 0 and newMark <= 100 then
            mark = newMark
        endif
    endprocedure
endclass

The private mark cannot be changed through the class interface unless the setter accepts it. The valid range from 0 to 100 is an example of an invariant, a rule that should remain true for every valid object.

Python equivalent

class ExamResult:
    def __init__(self, start_mark):
        self.__mark = start_mark

    def get_mark(self):
        return self.__mark

    def set_mark(self, new_mark):
        if 0 <= new_mark <= 100:
            self.__mark = new_mark
            return True
        return False

Python does not enforce privacy in exactly the same way as the conceptual model used in OCR pseudocode. A name beginning with two underscores is changed internally to discourage direct access. In these tasks, the important design idea is that other code uses the public methods rather than bypassing the validation.

Worked example
class TemperatureSensor:
    def __init__(self, temperature):
        self.__temperature = temperature

    def get_temperature(self):
        return self.__temperature

    def set_temperature(self, new_temperature):
        if -50 <= new_temperature <= 100:
            self.__temperature = new_temperature
            return True
        return False


sensor = TemperatureSensor(18)
print(sensor.get_temperature())
print(sensor.set_temperature(24))
print(sensor.set_temperature(180))
print(sensor.get_temperature())
Fill in the blanks
Combining data with the methods that control it: ______. Member intended for use only inside its class: ______. Method that returns a stored value: ______. Method that changes a stored value: ______. Member available through the class interface: ______.
  • encapsulation
  • private
  • getter
  • setter
  • public
Multiple choice1 mark

Which description best matches a getter function?

  • AIt always creates a new object.
  • BIt changes every private attribute in a class.
  • CIt returns a value without needing to change the object's state.
  • DIt makes a private attribute directly public.

Checkpoint: follow a requested state change

In the temperature-sensor example, trace these two requests separately:

  1. set_temperature(24) passes the range check, so the private value changes and the method returns True.
  2. set_temperature(180) fails the check, so the private value stays at 24 and the method returns False.

The rejected request is important: a setter must not partly update the object before discovering that the value is invalid.

Guided modification

Run the BankAccount code first. Then add a withdrawal method which changes the balance only when the amount is positive and no greater than the current balance. Test one accepted withdrawal and one rejected withdrawal.

Independent result task

Build the ExamResult class in this order:

  1. Store the starting mark in the private __mark attribute.
  2. Return it through get_mark().
  3. Validate the inclusive range 0 to 100 in set_mark().
  4. Return True for an accepted change and False for a rejected one.
  5. Create the required object and attempt the invalid change.

Use the exact public method and object names so that the checks can call them.

Starter code
class BankAccount:
    def __init__(self, opening_balance):
        self.__balance = opening_balance

    def get_balance(self):
        return self.__balance

    # Add withdraw(amount).
    # A withdrawal succeeds only when:
    # - amount is greater than 0
    # - amount is no greater than the balance
    # Return True for success and False otherwise.


account = BankAccount(80)
# Try withdrawing 25, then print the balance.
# Also try withdrawing 100 and check that the balance does not change.
Coding task4 marks
# Complete ExamResult.
# The valid mark range is 0 to 100 inclusive.
# A valid set_mark() call changes the mark and returns True.
# An invalid call leaves the mark unchanged and returns False.

class ExamResult:
    def __init__(self, start_mark):
        pass

    def get_mark(self):
        pass

    def set_mark(self, new_mark):
        pass


result = ExamResult(72)
invalid_change = result.set_mark(105)
Written answer3 marks

A school system stores each student's attendance percentage. Explain how encapsulation could help keep this value valid.

Name the private data, describe the public method used to change it, and explain what the validation prevents.

Students type their answer here.

Independent task: protect a changing score

A player's score must never decrease through add_points(). The method should accept zero or a positive number and reject a negative number.

Complete the class, then use the supplied calls to record whether each update was accepted. The expected final score is 15: the first update adds 5 and the negative update is ignored.

The checks use the public getter. They do not require outside code to access the private attribute.

Coding task4 marks
class PlayerScore:
    def __init__(self, starting_score):
        # Store starting_score privately.
        pass

    def get_score(self):
        pass

    def add_points(self, points):
        # Accept points >= 0 and return True.
        # Reject negative points and return False.
        pass


score = PlayerScore(10)
accepted_change = score.add_points(5)
rejected_change = score.add_points(-3)
Written answer2 marks

State one difference between a getter and a setter. Then explain one benefit of keeping an attribute private.

Give one precise comparison and one linked benefit.

Students type their answer here.