PHP面向对象编程:函数参数正确使用及对象攻击减血错误排查
Hey there! Let's break down why you're hitting those Trying to get property of non-object and Attempt to assign property of non-object errors, and get your fighter attack functionality working smoothly.
What's Causing the Errors?
Those warnings boil down to one core issue: you're trying to access or modify a property (like health) on something that isn't a Fighter object. The most common reasons this happens are:
- Passing a fighter's name as a string to your attack method instead of the actual object instance
- Forgetting to properly instantiate your Fighter class (e.g., using
$matt = "Matt"instead ofnew Fighter("Matt")) - Skipping type checks to ensure your attack method only accepts valid Fighter objects
A Working Implementation Example
Let's start with a solid Fighter class structure that handles attacks correctly:
class Fighter { // Public properties for name and health (you can use getters/setters later for better encapsulation) public $name; public $health; // Constructor to initialize each fighter with a name and default health value public function __construct($name, $health = 100) { $this->name = $name; $this->health = $health; } // Attack method with a type hint to ensure only Fighter objects are accepted public function attack(Fighter $target) { $damage = 10; // Adjust this value to set how much damage each attack does $target->health -= $damage; // Optional feedback to confirm the attack worked echo "{$this->name} hits {$target->name} for {$damage} damage! {$target->name}'s health is now {$target->health}\n"; } }
Now let's use this class to create your fighters and test the attack functionality:
// Create two valid Fighter instances $john = new Fighter("John"); $matt = new Fighter("Matt"); // Make John attack Matt $john->attack($matt); // Check Matt's updated health echo "Matt's current health: " . $matt->health;
Why This Works
- The
attackmethod uses a type hint (Fighter $target) which forces PHP to only accept Fighter objects. If you try to pass a string or anything else, PHP will throw a clear, actionable error immediately—way easier to debug than vague notices. - Objects are passed by reference in PHP, so modifying the
$targetobject'shealthproperty inside theattackmethod will persist outside the method (exactly what you want for reducing Matt's health).
Common Mistakes to Avoid
- ❌ Bad: Passing a name string instead of the object:
$john->attack("Matt"); // This will trigger your original errors! - ❌ Bad: Not instantiating the Fighter class properly:
$matt = "Matt"; // $matt is a string, not a Fighter object $john->attack($matt); - ✅ Good: Always pass the actual Fighter instance to the attack method.
Bonus: Cleaner Encapsulation (Optional)
For more robust code, you can use private properties with getter/setter methods to control how health is modified (like preventing negative health values):
class Fighter { private $name; private $health; public function __construct($name, $health = 100) { $this->name = $name; $this->health = max(0, $health); // Ensure health can't start negative } public function getName() { return $this->name; } public function getHealth() { return $this->health; } public function takeDamage($amount) { $this->health = max(0, $this->health - $amount); // Prevent health from dropping below 0 } public function attack(Fighter $target) { $damage = 10; $target->takeDamage($damage); echo "{$this->getName()} hits {$target->getName()} for {$damage} damage! {$target->getName()}'s health is now {$target->getHealth()}\n"; } }
This approach keeps internal properties private and adds guardrails to your logic—great for building more maintainable code.
内容的提问来源于stack exchange,提问作者AdrenalinMaster

