理解OOP的概念[关闭]

Apologies for the potentially super simple question. I am trying to understand OOP. I have gone through tutorials but many of them are hyper simplified and by giving myself a 'real' project I am hitting obstacles most tutorials don't seem to cover. Heres a scenario I kind of wish to understand:

If I was making a very basic sports game (think Fifa) I currently have 3 objects:

  • Object of Pitch
  • Object of Team
  • Object of Player

I am hitting my first wall of understanding because I don't want player to simply be an extension of team. After all in real life we would all be objects of human with an attribute that tells us which team we belong to before we are a sub object of a team.

What is the best practise for this?

Should I be:

  1. Creating the objects of player and then adding each object to an array which is stored against the team object? This is how I would do it procedurally.
  2. Storing the team against the player.
  3. Storing the player against the team.
  4. Extending player by team (I want to avoid this unless its actually the done thing)

This is just a brain exercise right now so I don't really have code but

$team1 = new teamObject('red');

$player1 = new players('John'); 
$team1->addToTeam($player1); 

This strikes me as it wouldn't work because in the teamObject Class I wouldn't be able to call any of the Player classes function on the passed player function?

This generally makes sense to me:

$team1 = new teamObject('red');
$player1 = new players('John'); 
$team1->addToTeam($player1); 

Although typically it would probably look more like this (but it's really the same thing):

$team1 = new Team('red');
$player1 = new Player('John'); 
$team1->addPlayer($player1); 

This strikes me as it wouldn't work because in the teamObject Class I wouldn't be able to call any of the Player classes function on the passed player function?

You certainly can call Player functions, because after adding the player to the team, the team will have a reference to the player(s). It can simply call player functions via that reference. A function in the team might use:

$this->players[0]->pretendToBeHurt();

You absolutely don't want to extend Team in this scenario.

In my experience many beginners make mistakes by being afraid of having too many classes. They try to use inheritance to somehow "save space" and end up with nonsensical object representations.

You are right to assume that a Player is not an extension of Team. Those are 2 different entities so thats a no to approach 4.

The way that these data structures will be held within each other really depends on the actual implementation and the data-model. I don't know how familiar you are with databases and data models but what we have here is a many-to-many relationship: a team has many players and a player can (in the course of his career) belong to multiple teams.

How you implement this relationship in PHP objects is then just the matter of how you want to use it. You will also find that often these objects are held in both places, using both your approaches 2 and 3.

  • Will you need to work with all the players in a team? Have an array of players stored in the Team object.
  • Will you need a list of all the teams in the player's career? Have an array of teams in the Player object.
  • Will you need the current team of a player? Have a single Team object in Player.
  • Will you need the Player who is the team captain? Have a single Player object in Team.
  • etc.

And yes, then you would have methods like:

$player->addToTeam($team1);

$team->addPlayer($player);

$team->addPlayers([
    $player1,
    $player2
]);

(As a side-note, have a look at PSR coding standards, name your classes capitalized and in singular form: Player, Team, Pitch. Reading through the document as soon as possible pays off.)