【问题标题】:Accessing instance of a package-private subclass as its public superclass访问包私有子类的实例作为其公共超类
【发布时间】:2016-03-27 19:24:27
【问题描述】:

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

我正在尽最大努力确保客户端和服务器包永远不会交叉路径,除非通过通用抽象进行通信。同样,游戏模型从不依赖于客户端或服务器的类。

但是我遇到了一个问题:

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

所以理想的解决方案(特别是针对播放器/用户问题)应该是这样的:

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

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

(另外,很明显,如果应用程序作为客户端运行,服务器只会向其发送信息以生成 Player 对象。用户只会被存储在专用/监听实例上。)

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

【问题讨论】:

  • 你不需要编译你当前的代码来尝试这个:只需在一个新项目中创建几个类。

标签: java inheritance subclass private superclass


【解决方案1】:

我同意你可以在一个新项目中快速充实这一点,但我很好奇它会如何运作,所以我还是这样做了:

一个播放器类:

package sandbox.pakcage1;

public class Player {
    public Player(String name) {
        this.name = name;
    }

    private String name;

    public String getName() {
        return name;
    }
}

一个用户类:

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());
        }
    }
}

您会发现 main 功能完美,从 User 对象访问 Player 数据成员就可以了。但是,您不能将它们转换为 User 对象,或者以任何方式访问 User 数据 - 因为该类在不同的包中受到包保护。

【讨论】:

    猜你喜欢
    • 2015-06-05
    • 2014-10-27
    • 2010-10-23
    • 2018-09-05
    • 1970-01-01
    • 2013-04-05
    • 1970-01-01
    • 1970-01-01
    • 2011-07-21
    相关资源
    最近更新 更多