Mastering Object Privacy in Object-Oriented Programming

Tackling Private Access in Java: Adding Journeys to SmartCards

In one of my recent projects, I encountered a common yet crucial hurdle—the challenge of handling access to private members in a class from another class. Specifically, my task involved manipulating instances of Journey linked to a SmartCard, but these instances were set as private. Here’s how I addressed this issue effectively, ensuring both functionality and encapsulation in object-oriented programming.

Understanding the Problem

The project involved two classes: Journey and SmartCard. Each SmartCard could have up to three Journey instances associated with it. The catch was that the Journey attributes (journey1, journey2, journey3) were private, making them inaccessible directly from other classes, like a managing SmartCardSystem.

Initially, I tried direct access and quickly realized the access restrictions—a solid foundation of OOP. My next attempt involved creating a getter method in the Journey class, but this didn’t solve the issue as the Journey instances themselves were not accessible for calling any method on them externally.

The Solution: Implementing Getter and Setter Methods

To manage the Journeys within a SmartCard, I implemented getter and setter methods within the SmartCard class. This approach preserved the encapsulation while allowing controlled access to the Journey instances. Here’s how I did it:

  1. Creating Getter and Setter Methods: I added methods in the SmartCard class to get and set the journeys. For every journey (journey1, journey2, journey3), I provided a getJourneyX() and setJourneyX(Journey journey) method. This enabled any external class to access or modify the journeys in a controlled manner.
  1. Conditional Logic for Journeys: Since SmartCard types “A” and “S” can have multiple journeys and type “C” only one, I included this logic within the setter methods. This ensured that we adhere to the business rules.

Here’s a simplified version of what those methods looked like:

public class SmartCard {
    private int cardID;
    private char type;
    private float balance;
    private Journey journey1 = null;
    private Journey journey2 = null;
    private Journey journey3 = null;

    public Journey getJourney1() {
        return this.journey1;
    }

    public void setJourney1(Journey journey) {
        if (journey != null) {
            this.journey1 = journey;
        }
    }

    public Journey getJourney2() {
        return type == 'A' || type == 'S' ? journey2 : null;
    }

    public void setJourney2(Journey journey) {
        if ((type == 'A' || type == 'S') && journey != null) {
            this.journey2 = journey;
        }
    }

    public Journey getJourney3() {
        return type == 'A' || type == 'S' ? journey3 : null;
    }

    public void setJourney3(Journey journey) {
        if ((type == 'A' || type == 'S') && journey != null) {
            this.journey3 = journey;
        }
    }
}

Adding New Journeys

To add a new journey, I used the setter methods. For example, if we need to add a journey to a SmartCard, we check if journey1 is null and set it; if not, then proceed to journey2, and so on. This ensured that the journeys are set in sequence while honoring the constraints of the smart card type.

This implementation not only solved the direct access issue but also kept the operations related to Journey management within the SmartCard, respecting the encapsulation principle in OOP.

Conclusion

By creating specific getter and setter methods in the SmartCard class, I managed to add new journeys while keeping the fields private. This method maintains the integrity and encapsulation of the data, ensuring that each component in our system interacts with others in a controlled and predictable manner. Handling private data often involves a fine balance between accessibility and protection, and in this case, carefully crafted accessors were the key.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *