如何使用 Java 这样的接口?

How to use Java Interfaces like this?

我正在开发一个程序,我想使用接口。有点像 Bukkit 用于他们的 Player class、here 的方式。我已经多次观看和阅读有关界面的教程,甚至尝试过自己进行测试,但没有成功。

假设我有一个 "User" 接口,带有一个 returns 字符串的方法占位符。该方法将被命名为 getName()。

我想做

User user = (INSTANTIATE SOMEHOW);
System.out.println(user.getName());

这在 Bukkit 的实现中以大致相同的方式实现

Player player = Server.getPlayer("Jimmothy");
System.out.println(player.getName());

我只是不知道如何让这样的东西发挥作用。为了实例化播放器 class,您可以使用许多 "getPlayer()" 方法中的一种。唯一的问题是包含这些方法的 classes 也是接口,所以我也不知道如何获取接口的实例。搜索代码也无济于事,因为我似乎无法找到那些 classes 中的方法在哪里以及是否实际上是使用 Overrides 或其他东西构建的。 (如果这是覆盖的工作方式)。

谁知道呢,也许我只需要知道如何实例化或获取用户界面的实例就可以了。我知道你不能使用 "new ClassName();" 创建接口实例我从来没有真正理解它们,但我真的很想。

这似乎是一个非常愚蠢的问题,我相信答案很简单,但帮助会很大! :) 感谢您的阅读。

恭喜,您找到了factory method!让我们直接跳到代码。

Test.java:

interface Player {
    String getName();
}

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

    @Override
    public String getName() {
        return name;
    }

    private String name;
}

class Server {
    public static Player getPlayer(String name) {
        return new PlayerImpl(name);
    }
}

public class Test {
    public static void main(String[] args) {
        Player foo = Server.getPlayer("foo");
        System.out.println(foo.getName());
    }
}

如您所见,Server class 有一个 static 方法返回类型 UserUserImpl 实例。这就是工厂方法。

这可能看起来(在本例中是)不必要的复杂化,但它有一个关键优势:它将某个 "concrete" class 的使用与其实现的接口分离.这允许更大的灵活性:

  1. 它隐藏了实现,让你可以自由切换多个不同的,只要它们都实现了User接口即可。从外面看,他们都一样。

  2. 它允许实现池化(每次你请求某个名称,你都会得到相同的实例)或任何其他分配策略。

  3. 它让您可以控制对象的创建。您可以执行检查等操作。

如果提供了工厂方法,则不应使用 new 实例化对象。如果您真的需要,您将不得不寻找该接口的实现。例如,PlayerImpl:

Player foo = new PlayerImpl("foo");

同样,这不是 PlayerImpl 应该使用的方式。

Bukkit 在 CraftBukkit 中实现了 Server(已通过 DMCA)。单例被传递给 Bukkit,您可以使用 Bukkit.getServer() 通过 API 检索它。但是,您对 Server#getPlayer(String) 方法的工作原理感兴趣。

CraftServer中具体实现了getPlayer(String)方法,它从玩家的名字中获取玩家。服务器中的玩家存储在集合 table 中,其中 name/UUID 到实际的 Player - 这是由 CraftPlayer 实现的。每次玩家加入时,都会实例化一个新的 CraftPlayer 并放入集合中。

因此,要自己执行此操作,您必须同时实现检索接口和要检索的实际对象。本质上:

interface Player {
    void kick(String message);
}

class CraftPlayer implements Player {
    @Override public void kick(String message) {
        // Implementation
    }
}

interface Server {
    Player getPlayer(String name);
}

class CraftServer implements Server {
    private final Map<String, Player> players = new HashMap<>();

    public CraftServer() {
        Bukkit.setServer(this);
    }

    @Override public Player getPlayer(String name) {
         return players.get(name);
    }

    public void joinPlayer(String name) {
        Player p = new CraftPlayer();
        players.put(name, p);
    }
}

class Bukkit {
    private Server server;
    public void setServer(Server server) {
        if (server == null) this.server = server;
    }

    public Server getServer() {
        return server;
    }
}

// Usage
new CraftServer();
Player p = Bukkit.getServer().getPlayer("Name");
if (p == null) {
    // Not online
    System.out.println("No player with that name is online");
    return;
}
p.kick("lol");