The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Object-oriented programming (OOP) rests on four ideas: abstraction, encapsulation, inheritance, and polymorphism, all built on classes and the objects created from them. A payroll run shows each one doing real work: different employees, different pay rules, and one loop that handles them all. The example is deliberately simplified and is a teaching tool, not payroll guidance.
The scenario: one simplified pay run
Imagine a program that runs once per pay period. It collects each person’s inputs (hours worked for some, nothing extra for others), asks each person’s pay policy to calculate gross pay, applies deduction steps, and prints a payroll register. Every rate and rule below is invented for teaching. None of it reflects current tax rules, worker classification, or any legal payroll requirement, and the class names do not decide anyone’s real-world status.
As an Amazon Associate I earn from qualifying purchases.
The code is Python, whose official tutorial chapter on classes (Python 3.14 documentation) describes a class as a bundle of data and functionality, where creating a class creates a new type. The ideas carry over to C#, Java, and ABAP Objects.
| Concept | What it does in the pay run |
|---|---|
| Class / object | Employee defines the type; “employee 1042” is one object of it |
| Abstraction | Model only what a pay run needs, such as ID, name, and how gross pay is calculated |
| Encapsulation | Hours and rates are set through methods that validate them |
| Inheritance | HourlyEmployee and SalariedEmployee reuse the base Employee |
| Polymorphism | The run calls calculate_gross_pay() on everyone; each type answers differently |
Class vs. object
A class is the definition of a type. An object is one instance of it, holding its own values. Python’s tutorial notes that instances carry attributes and use methods to change their state.
#1 Best Overall
class Employee:
def __init__(self, employee_id, name):
self.employee_id = employee_id
self.name = name
ana = Employee(1042, "Ana")
raj = Employee(1043, "Raj")
Employee is the class. ana and raj are two objects: same shape, different state. Change one and the other is unaffected.
Abstraction: model only what the pay run needs
Microsoft Learn’s C# object-oriented programming tutorial describes abstraction as modeling the relevant attributes and interactions of a system as classes. A real employee has a home address, a manager, a history, a shoe size. The pay run needs an identifier, a display name, and a way to get gross pay. So that is all Employee exposes here.
from abc import ABC, abstractmethod
class Employee(ABC):
def __init__(self, employee_id, name):
self.employee_id = employee_id
self.name = name
@abstractmethod
def calculate_gross_pay(self):
"""Return gross pay for the current period."""
The abstract method states the contract without saying how any policy fulfils it. What counts as “relevant” depends on the system: an HR directory would model very different things from the same person.
Rank #2
Encapsulation: control how state changes
Encapsulation hides internal state and functionality behind a public interface. Microsoft Learn describes it as allowing access through public functions, and SAP’s ABAP Objects documentation likewise treats it as a core object-oriented concept. In the pay run, outside code should not be able to overwrite a calculated total or push in negative hours.
class HourlyEmployee(Employee):
def __init__(self, employee_id, name, hourly_rate):
super().__init__(employee_id, name)
self._hourly_rate = hourly_rate
self._hours_worked = 0
def record_hours(self, hours):
if hours < 0 or hours > 300: # illustrative sanity limit
raise ValueError("Hours out of range for one period")
self._hours_worked = hours
def calculate_gross_pay(self):
return round(self._hours_worked * self._hourly_rate, 2)
The validation rule (300 hours) is a made-up guard, not a legal limit. One Python-specific caveat: the leading underscore in _hours_worked is a naming convention that tells other developers “internal”, not an enforced lock. Languages such as C# and Java offer private members that the compiler enforces. The design intent, a narrow public door, is the same.
A second practical note: real money code generally avoids binary floating point. Python’s decimal.Decimal is the usual choice. The examples use plain numbers to keep the concepts visible.
Inheritance: specialize a shared type
Microsoft Learn describes inheritance as creating classes that reuse, extend, and modify behavior defined in another class. Here, both employee kinds share an ID and name, so they inherit from Employee and add only what differs.
class SalariedEmployee(Employee):
def __init__(self, employee_id, name, period_salary):
super().__init__(employee_id, name)
self._period_salary = period_salary
def calculate_gross_pay(self):
return round(self._period_salary, 2)
Treat this hierarchy as a teaching device. Real classification of workers is a legal and contractual matter that a class name cannot capture, and inheritance is not required for every design. A deep tree of subclasses can become rigid; if what varies is a pay rule rather than a kind of person, a separate policy object (below) can be cleaner.
Polymorphism: one call, different behavior
SAP’s documentation explains that same-named methods can behave differently in different classes, and Microsoft’s tutorial demonstrates the same through derived implementations. The payroll loop does not need to know which kind of employee it holds.
Rank #4
ana = HourlyEmployee(1042, "Ana", hourly_rate=20.00)
ana.record_hours(80)
raj = SalariedEmployee(1043, "Raj", period_salary=2500.00)
for emp in [ana, raj]:
print(emp.employee_id, emp.name, emp.calculate_gross_pay())
Expected output (with the invented numbers above):
1042 Ana 1600.0
1043 Raj 2500.0
Adding a new kind of pay later means writing a new class with its own calculate_gross_pay. The loop stays unchanged. That extensibility is the real payoff, more than the keyword itself.
Extending the run without breaking it
Deductions are a good second use of the same ideas. Rather than hard-coding them inside employees, define a small interface and let the run apply a list of them.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →class Deduction(ABC):
@abstractmethod
def amount(self, gross):
...
class FlatDeduction(Deduction):
def __init__(self, value):
self._value = value
def amount(self, gross):
return self._value
class PercentDeduction(Deduction):
def __init__(self, percent):
self._percent = percent
def amount(self, gross):
return round(gross * self._percent / 100, 2)
deductions = [FlatDeduction(25.00), PercentDeduction(5)]
for emp in [ana, raj]:
gross = emp.calculate_gross_pay()
net = gross - sum(d.amount(gross) for d in deductions)
print(emp.name, gross, round(net, 2))
The 5% and flat amount are placeholders. Real withholding depends on jurisdiction, the date, and the individual’s circumstances, so production systems take those rules from maintained, authoritative configuration rather than from constants in code.
Best Value
Judging a design: four review questions
These are practical questions derived from how the mechanisms work, not benchmarks or rankings:
- Shared interface: does every pay behavior answer the same call, so the loop needs no type checks?
- Real variety: are there genuinely different behaviors? With only one rule, a plain function may beat a class hierarchy.
- Controlled inputs and results: can outside code set hours or totals only through validating methods?
- Ease of adding a policy: can a new rule be added by writing one class instead of editing several
ifbranches?
Payroll here is only an example domain. It is not evidence that one hierarchy, or any formula shown, suits a real payroll system.
Why this beats animals and shapes
Dog and Cat examples show syntax but not motivation. A pay run shows why the ideas exist: many records to process, rules that differ per case, values that must not be corrupted, and a business that keeps adding new cases. Microsoft Learn introduces the four principles with the line “The four basic principles of object-oriented programming are:” and then walks through abstraction, encapsulation, inheritance, and polymorphism. Each of those solves one problem in the code above.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




