如何使用 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
方法返回类型 User
的 UserImpl
实例。这就是工厂方法。
这可能看起来(在本例中是)不必要的复杂化,但它有一个关键优势:它将某个 "concrete" class 的使用与其实现的接口分离.这允许更大的灵活性:
它隐藏了实现,让你可以自由切换多个不同的,只要它们都实现了User
接口即可。从外面看,他们都一样。
它允许实现池化(每次你请求某个名称,你都会得到相同的实例)或任何其他分配策略。
它让您可以控制对象的创建。您可以执行检查等操作。
如果提供了工厂方法,则不应使用 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");
我正在开发一个程序,我想使用接口。有点像 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
方法返回类型 User
的 UserImpl
实例。这就是工厂方法。
这可能看起来(在本例中是)不必要的复杂化,但它有一个关键优势:它将某个 "concrete" class 的使用与其实现的接口分离.这允许更大的灵活性:
它隐藏了实现,让你可以自由切换多个不同的,只要它们都实现了
User
接口即可。从外面看,他们都一样。它允许实现池化(每次你请求某个名称,你都会得到相同的实例)或任何其他分配策略。
它让您可以控制对象的创建。您可以执行检查等操作。
如果提供了工厂方法,则不应使用 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");