Featured image of post Understanding OOP Access Modifiers: Public, Private, Protected, and Default

Understanding OOP Access Modifiers: Public, Private, Protected, and Default

A beginner-friendly guide to access control in Object-Oriented Programming, featuring real-world analogies, comparison tables, and code examples in Java and Python.

When you start learning Object-Oriented Programming (OOP), you’ll quickly run into terms like public, private, protected, and sometimes default. These are called Access Modifiers (or Access Specifiers).

But what are they, and why do they matter?

Think of access modifiers as the security guards of your code. They control who can see and use the variables (attributes) and functions (methods) inside your classes. Without them, any part of your program could change anything else, leading to hard-to-find bugs and chaotic code.

Let’s break them down using a simple real-world analogy: Your House.


The House Analogy

Imagine you own a beautiful house. The different parts of your house have different levels of access:

Access ModifierAnalogyWho Can Access?
publicThe front yard & mailboxAnyone walking down the street.
default (Package-Private)The shared apartment corridorOnly neighbors who live in the same building/folder.
protectedThe family living roomOnly you and your children (and descendants).
privateYour personal locked diaryOnly you (nobody else, not even your children).

Let’s dive deeper into each of these.


1. Public: Open to the World

The public modifier is the least restrictive. When a variable or method is marked as public, it means it can be accessed from anywhere in your program.

  • Analogy: Your front yard. Anyone can walk up, look at it, or drop a letter in your mailbox.
  • When to use: For methods or attributes that you want other parts of your program to interact with (like a button’s click() action or a library’s utility function).

Java Example

In Java, we use the public keyword:

1
2
3
public class House {
    public String mailbox = "Hello!"; // Accessible from anywhere
}

Python Example

In Python, all attributes and methods are public by default! You don’t need any special keywords:

1
2
3
class House:
    def __init__(self):
        self.mailbox = "Hello!" # Public attribute

2. Private: For Your Eyes Only

The private modifier is the most restrictive. A private variable or method can only be accessed from inside the class it was created in. External classes, and even subclasses (child classes), cannot access it.

  • Analogy: Your personal locked diary. Only you can read or write in it. If your children want to read it, they can’t.
  • When to use: To protect sensitive data (like passwords, balances, or internal system configurations) from being changed incorrectly.

Java Example

In Java, we use the private keyword:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class House {
    private String diary = "Dear Diary, today I learned OOP..."; // Only visible inside House class
    
    // We can expose a public method to let others view it safely (Getter)
    public String getDiaryEntry(String password) {
        if ("supersecret".equals(password)) {
            return this.diary;
        }
        return "Access Denied!";
    }
}

Python Example

Python doesn’t have strict private enforcement, but it uses a naming convention: prefixing a name with a double underscore (__). This triggers name mangling, making it harder to access from outside:

1
2
3
4
5
6
7
8
class House:
    def __init__(self):
        self.__diary = "Dear Diary, today I learned OOP..." # Private attribute
        
    def get_diary_entry(self, password):
        if password == "supersecret":
            return self.__diary
        return "Access Denied!"

3. Protected: Family-Only Access

The protected modifier is a middle ground. It allows access by the class itself, subclasses (child classes that inherit from it), and classes in the same package/folder.

  • Analogy: The family living room. Friends from other neighborhoods can’t walk in, but your children (subclasses) have full access to it, even if they move out to their own houses.
  • When to use: When you are building a class hierarchy and want child classes to inherit and use/modify internal attributes, but want to hide them from the general public.

Java Example

In Java, we use the protected keyword:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public class ParentHouse {
    protected String familyHeirloom = "Golden Pocket Watch"; // Accessible by subclasses
}

public class ChildHouse extends ParentHouse {
    public void showHeirloom() {
        // Child class can access the parent's protected attribute!
        System.out.println("Inherited heirloom: " + this.familyHeirloom);
    }
}

Python Example

In Python, we denote a protected attribute by prefixing it with a single underscore (_). This is a convention—it tells other programmers “please don’t touch this from outside,” though Python won’t strictly block them:

1
2
3
4
5
6
7
8
class ParentHouse:
    def __init__(self):
        self._family_heirloom = "Golden Pocket Watch" # Protected attribute (by convention)

class ChildHouse(ParentHouse):
    def show_heirloom(self):
        # Child can access it safely
        print(f"Inherited heirloom: {self._family_heirloom}")

4. Default: The Neighborhood Scope

In some languages like Java, if you do not specify any access modifier, it defaults to a specific access level. In Java, this is known as package-private (often called default).

  • Analogy: The shared corridor in an apartment building. Anyone living in the same building (same package/folder) can walk through it, but outsiders from other buildings cannot.
  • When to use: When you want classes within the same functional module (package) to work closely together without exposing those helper methods to the rest of the application.

Java Example

In Java, you specify default access by simply omitting the access modifier keyword:

1
2
3
class House {
    String apartmentCorridor = "Shared hallway"; // Default (package-private) access
}

Python Example

Python does not have packages in the same compile-time scope sense for variable scoping. Since there is no default modifier in Python, standard public attributes are typically used, or modules are kept clean by prefixing internal helper classes/functions with a single underscore to keep them module-private.


Access Modifiers Cheat Sheet

Here is a handy comparison chart summarizing who can access what in Java (since Java supports all four modifiers explicitly):

ModifierInside ClassSame PackageSubclass (Diff Package)World (Diff Package)
publicYesYesYesYes
protectedYesYesYesNo
default (No keyword)YesYesNoNo
privateYesNoNoNo

Summary: How to Choose?

When deciding which access modifier to use, always start with the Principle of Least Privilege:

  1. Make everything private by default.
  2. If subclasses need access, change it to protected.
  3. If classes in the same module/package need access, use default.
  4. Only make it public if it’s absolutely necessary for the outside world to interact with it.

By keeping access as restricted as possible, you protect your objects from being put into invalid states, making your code easier to debug, maintain, and extend!

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy