Example of Good Foreign Object Handling
Date: 2025 10-October 30
That is a comprehensive request! You're looking for a rigorous, side-by-side comparison of Query (Calculation) methods versus Setter (Command) methods, and how the principle of Encapsulation applies across different method types (static, class, instance), especially concerning foreign objects.
Here is a full analysis using a sample Client class.
1. 🔍 Core Concepts
| Concept | Description |
|---|---|
| Query | A method that returns a value but does not change the state of the object (self) or the class (cls). |
| Setter (Command) | A method that changes the state of the object (self) or the class (cls) but does not typically return a useful value (often returns None or self). |
| Encapsulation | The principle that an object's internal state (attributes) should only be accessed or modified by the object's own methods. |
| Foreign Object Violation | A method on one object (A) reaching into and modifying the state of another object (B) directly. This breaks Encapsulation. |
2. 🆚 Query vs. Setter Analysis by Method Type
The primary distinction between Query and Setter is what the method acts upon and what it returns.
A. Instance Methods (Standard OOP)
| Pattern | Query (Calculation) | Setter (Command) |
|---|---|---|
| Example | client.get_status() |
client.set_status('active') |
| Code | def get_status(self): return self.status |
def set_status(self, status): self.status = status |
| Encapsulation | Good. Accesses self's state but only returns it. |
Good. Modifies self's state via its own method. |
B. Class Methods (@classmethod)
| Pattern | Query (Class Data) | Setter (Class State Change) |
|---|---|---|
| Example | Client.get_max_limit() |
Client.set_max_limit(500) |
| Code | def get_limit(cls): return cls.MAX_LIMIT |
def set_limit(cls, limit): cls.MAX_LIMIT = limit |
| Encapsulation | Good. Accesses cls state via the defined method. |
Good. Modifies cls state via the defined method. |
C. Static Methods (@staticmethod)
| Pattern | Query (Utility Calculation) | Setter (Not Applicable) |
|---|---|---|
| Example | Client.validate_input(data) |
N/A |
| Code | def validate(data): return data > 0 |
Cannot access or modify self or cls state. It can only modify objects passed into it (see Section 3). |
| Encapsulation | N/A. Does not interact with class or instance state. | N/A. |
3. 🛡️ Foreign Object Handling: Encapsulation
This section addresses the crucial difference between passing a foreign object as data and using a method to change its state.
A. Foreign Object Violation (BAD Practice) ❌
This breaks encapsulation because Client's method is managing Other's state.
| Method Type | Violation Example | Why it's a Violation |
|---|---|---|
| Instance | client.update_other(other): other.value = 10 |
client is reaching into the internal state of the other object directly. The Other object loses control over its state transitions. |
| Static | Client.update_other(other): other.value = 10 |
The static method is acting as a global function to mutate the other object, bypassing other's own methods. |
B. Good Foreign Object Handling (GOOD Practice) ✅
This respects encapsulation because Client's method uses the foreign object's own defined interface (its methods) to request a change, or simply uses it as data.
| Method Type | Good Handling Example | Why it's Good |
|---|---|---|
| Instance | client.process_other(other): other.request_update(client.data) |
client tells other what to do (request_update), but other's method decides how to change its internal state. |
| Static | Client.get_data_from_other(other): return other.report() |
The method uses other as a data source (a Query) but does not attempt to modify its state. |
4. 📝 Code Example Synthesis
Here is how you would use these principles in a single Client class, using an Other object.
Python
class Other:
def __init__(self, value):
self._internal_value = value
# The only way to change the value (GOOD ENCAPSULATION)
def set_value(self, new_value):
print(f"[Other] State changing from {self._internal_value} to {new_value}")
self._internal_value = new_value
class Client:
MAX_COUNT = 100
def __init__(self, count=0):
self.count = count
# GOOD: Instance Method (Setter)
def increment(self, step):
"""Changes only the state of self."""
self.count += step
# BAD: Instance Method (Foreign Object Violation) ❌
def violate_other(self, other: Other, new_value):
# Direct modification of a foreign object's internal attribute
other._internal_value = new_value # VIOLATION!
# GOOD: Instance Method (Good Foreign Object Handling) ✅
def update_other_safely(self, other: Other, new_value):
# Delegates the state change to the 'other' object itself
other.set_value(new_value)
# GOOD: Static Method (Utility Query)
@staticmethod
def calc_new_limit(base: int) -> int:
"""Utility that calculates a value without touching state."""
return base * 2
# GOOD: Class Method (Class Setter)
@classmethod
def set_max_count(cls, new_max):
"""Changes only the state of the class."""
cls.MAX_COUNT = new_max