代码之家  ›  专栏  ›  技术社区  ›  and0

访问包私有子类的实例作为其公共超类

  •  -3
  • and0  · 技术社区  · 9 年前

    我正在编写一个多人游戏引擎,我将传统的MVC模式映射到game/Client/Server(游戏是其他部分作用和通信的“模型”。客户端内部有自己的MVC结构。)

    我正在尽我所能确保客户端和服务器包永远不会交叉,除非通过公共抽象进行通信。类似地,游戏模型从不依赖于客户端或服务器的类。

    然而,我遇到了一个问题:

    • 服务器显然知道客户机不需要的大量信息。例如,尽管客户端需要知道其他连接的玩家对象(带有“昵称”和“ping”等信息),但他们当然不需要知道其他玩家的IP地址、连接时间、帐户信息等。
    • 这导致我编写表示相同信息的包特定类。例如,在游戏模型中,我有一个用于所有连接用户的Player对象,但在服务器包中有一个相应的User对象存储其他信息。两个包中都有一个HashMap,它存储了相应的对象,并用相同的ID绑定。
    • (我的项目中有一堆相同模式的实例。一些信息位于游戏模型中,而在服务器模型中有一个对应的对象,其中包含服务器需要的其他信息。)
    • 这并不理想,因为我现在需要确保更改(如播放器断开连接)反映在多个区域。

    因此,理想的解决方案(尤其是针对玩家/用户问题)如下:

    • Game包中有一个Player类,它只有Game和Client需要的字段和方法。
    • 有一个子类叫做User声明 私下地 在服务器包中。此类具有用于连接和身份验证的方法和字段。
    • 游戏模型中有一个HashMap,它存储玩家,由(int)ID映射。
    • 如果应用程序作为侦听或专用服务器运行, 的这个HashMap实际上会填充User对象 .

    那么,我的问题是 Game和Client包是否可以作为公共超类(Player)访问这些对象,即使实际上它是属于另一个包的子类的实例? 从游戏和客户端的角度来看,他们只需要访问超类方法/字段。

    (同样,很明显,如果应用程序作为客户端运行,服务器将只发送信息以使播放器成为对象。用户将只存储在专用/侦听实例中。)

    我会测试这一点,但我的游戏远没有编译(目前正在经历重构噩梦,新手错误需要清理),我不确定IDE是否会检测到任何运行时冲突。

    1 回复  |  直到 9 年前
        1
  •  0
  •   Frank    9 年前

    我同意你可以在一个新项目中很快地实现这一点,但我很好奇它到底会如何实现,所以我还是这么做了:

    A Player类:

    package sandbox.pakcage1;
    
    public class Player {
        public Player(String name) {
            this.name = name;
        }
    
        private String name;
    
        public String getName() {
            return name;
        }
    }
    

    A用户类:

    package sandbox.package2;
    
    import sandbox.pakcage1.Player;
    
    class User extends Player {
        private String userID;
    
        public User(String name, String id) {
            super(name);
            this.userID = id;
        }
    
        public String getUserID() {
            return userID;
        }
    }
    

    生成一些用户的类:

    package sandbox.package2;
    
    import java.util.ArrayList;
    import java.util.List;
    import sandbox.pakcage1.Player;
    
    public class UserBuilder {
        public static List<Player> getUsers() {
            List<Player> users = new ArrayList<>();
    
            users.add(new User("Joe", "1"));
            users.add(new User("Bob", "2"));
    
            return users;
        }
    }
    

    还有一条主线将其连接在一起:

    package sandbox;
    
    import java.util.List;
    import sandbox.package2.UserBuilder;
    import sandbox.pakcage1.Player;
    
    public class Sandbox {
        public static void main(String[] args) {
            List<Player> players = UserBuilder.getUsers();
    
            for(Player player : players) {
                System.out.println(player.getName());
            }
        }
    }
    

    您会发现,主要功能非常完美,从User对象访问Player数据成员也很好。但是,您不能将它们强制转换为User对象,也不能以任何方式访问User数据,因为该类在不同的包中受包保护。