【问题标题】:How do I make two objects of the same class communicate /w each other?如何使同一类的两个对象相互通信/相互通信?
【发布时间】:2021-02-06 23:50:23
【问题描述】:

我想让同一类的两个对象互相“交谈”。

我想按照描述的做,但不知道怎么做,我没有找到解决方案:

public class Player  {
    boolean initiative;
    static int counter;
    Player () {
        if (counter == 0) {
            initiative = true;
        } else { 
            initiative = false;
        }
        counter++;
    }
    
    setInitiative (boolean switch){
        //problem is here:
        //if switch true, change all other objects to false
        //if switch false do nothing (not the problem ;))
    }
}

    public class Main {
        var player1 = new Player(); //constructs player1.initiative == true
        var player2 = new Player(); //constructs player2.initiative == false

        player2.setInitiative (true); //should change player1.initiative to false
        System.out.print (player1.initiative);
    }

Outputs>>> false

那么我的 setInitiative 方法必须如何查看才能给出我的结果? 有没有办法一次与一个类的所有实例进行通信?

【问题讨论】:

  • 如果您想“一次与类的所有实例通信”,请将initiative 设为静态。但是,所有个玩家将具有相同的价值。
  • 看来initiative 并不是一个真正的单人游戏对象的合理状态。看起来您可能需要另一个类,例如 Game 来保存当前具有主动权的玩家(这可以通过简单地使用类似 Player playerWithInitiative 的字段来完成)。
  • 没有这样的“观察者”类是否可行?也许制作一个静态列表之类的东西,它通过构造函数保存我的所有对象? id 给出列表索引,循环设置除方法调用者之外的所有其他值?但可能有点奇怪。
  • 这并非不可能,但这是非常糟糕的做法。拥有一个观察者类会更好地保持结构。
  • 感谢大家!你现在帮了我很大忙! :-) 如何在特殊情况下将随机主动权分配给“玩家”对象之一?我可以让我的观察者知道,有哪些玩家以及有多少玩家?

标签: java oop object instance


【解决方案1】:

您的问题询问如何链接同一类的两个实例,还询问如何链接同一类的所有实例。有几种方法可以实现这两种方法,因此我将建议一种简单的方法来实现每种方法,然后稍微更改设计以简化。

链接两个实例

public class Main {
    public static void main(String[] args) {
        Player player1 = new Player();
        Player player2 = new Player();

        player2.setInitiative(true);
        System.out.print (player1.initiative);
    }
}

class Player  {
    Player linkedPlayer;
    boolean initiative;
    static int counter;
    
    Player () {
        if (counter == 0) {
            initiative = true;
        } else { 
            initiative = false;
        }
        counter++;
    }
    
    static void linkPlayers(Player a, Player b) {
        a.linkedPlayer = b;
        b.linkedPlayer = a;
    }
    
    void setInitiative (boolean newInitiative) {
        initiative = newInitiative;
        if (linkedPlayer != null) {
            linkedPlayer.initiative = !newInitiative;
        }
    }
}

这有一些缺点:

  • 创建后必须链接实例。
  • 您必须为三人游戏更改程序结构。

链接所有实例

我不知道如何发现类的所有实例,但您可以在创建它们时将它们添加到列表中。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Player player1 = new Player();
        Player player2 = new Player();
        Player player3 = new Player();

        player2.takeInitiative();
        System.out.println(player1.initiative);
        System.out.println(player2.initiative);
        System.out.println(player3.initiative);
    }
}

class Player  {
    private static List<Player> allPlayers = new ArrayList<>();
    
    boolean initiative;
    
    Player () {
        initiative = allPlayers.isEmpty();
        allPlayers.add(this);
    }
    
    void takeInitiative () {
        for (Player p : allPlayers) {
            p.initiative = false;
        }
        initiative = true;
    }
}

我更改了设置主动方法。如果有两个以上的玩家,当一个玩家失去主动权时会发生什么还不清楚。别人得到它,还是没有人得到它。

代码可能看起来更干净,但实际上,静态列表存在重大设计问题:

  • 它会阻止您的程序轻松包含一组以上的玩家(可能同时运行多个游戏)。
  • 它可以防止任何玩家被垃圾收集器清理,因为列表将始终具有引用。您可以通过某种弱参考来缓解这种情况,但我更愿意解决设计问题。

让我们从玩家类中取出所有巧妙的逻辑,并将其放入游戏类中。

import java.util.*;

public class Game {
    public static void main(String[] args) {
        Player player1, player2, player3;
        
        List<Player> allPlayers = new ArrayList<>();
        allPlayers.add(player1 = new Player(true));
        allPlayers.add(player2 = new Player(false));
        allPlayers.add(player3 = new Player(false));

        assignInitiative(player2, allPlayers);
        System.out.println(player1.initiative);
        System.out.println(player2.initiative);
        System.out.println(player3.initiative);
    }
    
    static void assignInitiative(Player takingInitiative, List<Player> allPlayers) {
        for (Player p : allPlayers) {
            p.setInitiative(false);
        }
        takingInitiative.setInitiative(true);
    }
}

class Player  {
    boolean initiative;
    
    Player (boolean initiative) {
        this.initiative = initiative;
    }
    
    void setInitiative (boolean newInitiative) {
        initiative = newInitiative;
    }
}

在这里,玩家是通过游戏类链接的。您保留了所有功能,但现在您可以在同一个程序中拥有多个游戏并修复了内存泄漏。

但是由于逻辑已经转移到游戏类,您可以进一步简化,使用一个变量来保持玩家的主动性。

public class Game {
    public static void main(String[] args) {
        Player player1 = new Player();
        Player player2 = new Player();
        Player player3 = new Player();
        
        Player initiativeHolder = player2;

        System.out.println(player1 == initiativeHolder);
        System.out.println(player2 == initiativeHolder);
        System.out.println(player3 == initiativeHolder);
    }
}

class Player  {
}

【讨论】:

  • 我认为这些方法最有帮助。 (是的,该倡议将永远只有一个玩家。)谢谢! :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-26
  • 2018-03-04
  • 2022-01-14
  • 2020-04-25
相关资源
最近更新 更多