1

To make this question clear, I show it in an example.

I have a simple class called Player, which contains three data members( "attack" which is important here), and have setters and getters for them. (only setAttack() which matters now). I have a "Team" class which will contain three Player objects, to make some operation on Players' fields. Also, Team class has a simple method named increaseattack(), which will increase a specific players attack by 1. (immediately called when Team object created through its constructor). In Match class I create 3 player objects, and a team object made by those. And now the fun starts: calling setAttack() inside Team class for the specified player will also change the originally created player's attack in Match class!

I know that I am wrong about somewhat basic conception, but do not know how Its properly done. Could you explain it to me, why is this working like that? Here is the source of the three classes:

public class Player {
  String name;
  int attack;
  int defense;

public Player(String name, int attack, int defense){
    this.name = name;
    this.attack = attack;
    this.defense = defense;
}

public int getAttack() {
    return attack;
}
public void setAttack(int attack) {
    this.attack = attack;
}
public int getDefense() {
    return defense;
}
public void setDefense(int defense) {
    this.defense = defense;
}
}


public class Team {
   private Player player1;
   private Player player2;
   private Player player3;

public Team(Player p1, Player p2, Player p3){
    this.player1 = p1;
    this.player2 = p2;
    this.player3 = p3;
    increaseattack(player1);
}

public void increaseattack(Player pla){
    pla.setAttack(pla.getAttack()+1);
}

}


public class Match {
 Player player, player2, player3;
 Team team, team1;
//static Player player, player2, player3;
//static Team team, team1;

public static void main(String[] args){
    new Match();
}

public Match(){
    test();
}


public void test() {
    player = new Player("Alan", 10, 10);
    player2 = new Player("Bob", 10, 12);
    player3 = new Player("Cedric", 13, 10);
    team = new Team(player,player2,player3);  // Creating the team instance based on player instances created here, OK 10+1 = 11
    team1 = new Team(player,player2,player3);  // new team, hopefully i get the same results, but thats not the case, 11 is base attack, not 10!!!
    System.out.println("------------------------");
    System.out.println(" " + player.getName() + " " + player.getAttack() + " " + player.getDefense());
    System.out.println(" " + player2.getName() + " " + player2.getAttack() + " " + player2.getDefense());
    System.out.println(" " + player3.getName() + " " + player3.getAttack() + " " + player3.getDefense());


}

}

Here's the output:

------------------------
Alan 12 10
Bob 10 12
Cedric 13 10

Which is not correct for me, as I expected Alan's original attack has not changed, only "in" the team. I appreciate any help. Thank you.

Newbie1001
  • 131
  • 11
  • you can do the instantiation inside the Team class as well – Stultuske Feb 14 '17 at 18:27
  • 1
    Alan's attack changes because when you create a team you increase the attack of the first player by 1, and you've added Alan to two teams. 10 + 1 + 1 = 12 – David Feb 14 '17 at 18:28
  • You seem to think that passing an object as argument causes a copy of the object to be made. That's not the case. A copy of the **reference** is made. See http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value. So alan, team.player and team1.player are 3 references to the same Player object. – JB Nizet Feb 14 '17 at 18:29
  • If composition pattern need access to outer class, something is wrong – Jacek Cz Feb 14 '17 at 18:36
  • JB Nizet that was exactly the case until now. Thank you for making it clear. :) – Newbie1001 Feb 14 '17 at 19:06

4 Answers4

0

Instead of doing this:

public void increaseattack(Player pla){
    pla.setAttack(pla.getAttack()+1);
}

define a method in the PLayer class and do the operation directly...

public void increaseAttack() {
    this.attack++;
}
ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
0

You Should Go Over Your Program Again. Your Constructor of team is adding "attack" to the first parameter.

public Team(Player p1, Player p2, Player p3){
this.player1 = p1;
//this.player2 = p2;
//this.player3 = p3;
increaseattack(player1);

Thats Why Alans Attack Got Increased.

Micael Illos
  • 467
  • 2
  • 15
0

You create a player with an attack of 10:

player = new Player("Alan", 10, 10);

Then you add that player to two teams:

team = new Team(player,player2,player3);
team1 = new Team(player,player2,player3);

What happens in the constructor of Team?:

this.player1 = p1;
//...
increaseattack(player1);

And what does increaseattack() do?:

pla.setAttack(pla.getAttack()+1);

So Alan's attack value goes from the original 10 to the new value of 12 because that last operation is performed on it twice, once for each team to which he is added.


Edit: Based on your comment below, it sounds like what you want to do is instead of asking the player what their attack is, as the team what the attack for a given player is. This is because the "attack modifier" on the "first" player is a team data element, not a player data element.

So perhaps on the Team class you may have something like:

public int getAttackFor(Player player) {
    if (player == player1) {
        return player.getAttack() + 1;
    }
    if ((player == player2) || (player == player3)) {
        return player.getAttack();
    }
    // throw an exception if the player isn't found?
}

This is just a quick free-hand idea, you might tweak it for your needs. Maybe compare based on a player identifier instead of direct object reference comparison, maybe put players into an array instead of comparing against individual variables, etc. But the idea would be:

  1. Supply a Player and ask for that player's attack for that team (since it is apparently potentially different than the player's attack alone)
  2. Determine if that Player incurs a "modified" attack
  3. Return the attack for that Player for that team.

So then to use it you'd do something like this in main():

System.out.println(" " + player.getName() + " " + team.getAttackFor(player) + " " + player.getDefense());
David
  • 208,112
  • 36
  • 198
  • 279
  • I know that. But I want to know how to increase Alan's attack in Team, and leave Alan's original value at his basics. To purpose of this, i want to simulate Alan statistics in multiple teams, for example Alans got increased statistics when playing with Cedric, and in another team Alan got nothing, just his original values, in another Alan is more defensive... etc... – Newbie1001 Feb 14 '17 at 18:42
  • @Newbie1001: The problem there is that when you call `player.getAttack()` there is no context of a "team". How would that line of code determine the team-modified attack? It sounds like what you want is to add a method to the `Team` object which would return an attack for a requested player, and within the `Team` class you would determine if that player is the "first" player and, if so, return `player.getAttack() + 1` instead of `player.getAttack()`. – David Feb 14 '17 at 18:57
  • @Newbie1001: I've updated the answer with an example of the idea. – David Feb 14 '17 at 19:07
  • Wow, thank you very much. :) That will solve my problem. I wonder why I stuck on doing it like a Player related instead of making it in Team class. Anyway thanks again. – Newbie1001 Feb 14 '17 at 19:21
0

From the test() method, you create three Player objects with the specified values.

You then create a Team object passing these three Player objects.

The team object's player variable points to your original Player objects. (You are just using different variable names to refer to same objects)

Hence, team object can change value of a member belonging to Player object. In your case passing:

"Alan", 10, 10
"Bob", 10, 12
"Cedric", 13, 10

to the team object changes the value of Alan's attack to 11.

So, new values are:

"Alan", 11, 10
"Bob", 10, 12
"Cedric", 13, 10

You then create another Team object "team1" passing these same Player objects. Alan's attack value is again incremented. So the new values are:

"Alan", 12, 10
"Bob", 10, 12
"Cedric", 13, 10

Hence your output.

Read this for more info: link