Java方法重载困惑

标签 java inheritance interface overloading

在服务器代码中,我有一个 ProtocolHandler 类,它从套接字读取数据,找出它正在处理的数据包类型并将其分派(dispatch)给客户端。我正在尝试拥有以下架构:

public interface Packet {
    //...
}

public class ClientInformations implements Packet {
    //...
}

public class ProtocolHandler {
    //....
    public void bytesReceived(byte[] bytes) {
        //... Determine the type of the packet
        Packet packet = determineTypeOfPacketAndRead(bytes);

        // Here  I already have the packet object built,
        // like ClientInformations@1a1a1a1a[...]

        client.packetReceived(packet);
    }
    //...
}

public class Client {
    //...
    public void packetReceived(Packet pkt) { 
        System.out.println("Unimplemented packet received.");
    }

    public void packetReceived(ClientInformations ci) {

    }

    //...
}

(我不知道如何简单地用语言来解释它)。问题是,我真的认为 packetReceived(ClientInformations) 会被调用,但事实并非如此。它调用更通用的 packetReceived(Packet) 方法。我错了吗?那我怎么还能使用相同的架构呢?

--编辑

现在我明白为什么会这样了。问题是,我还有其他数据包类,例如 MovementSyncSpawn。我想通过向 Client 类添加一个新方法来简化添加新数据包的过程。那么没有另一种方法吗?我的意思是,有一种方法可以在运行时自动分析packet 对象的类型并进行最具体的方法调用吗?

最佳答案

我假设您有 Packet packet = determineTYpeOfPacketAndRead(bytes),因为几乎没有其他方法可以编译代码。

所以 reference 类型是 Packet(在编译时),即使 object 类型是 ClientInformations(在运行时)。

并且如 Java 语言规范第 15 章所述方法重载

The most specific method is chosen at compile-time; its descriptor determines what method is actually executed at run-time.

更新:您的代码目前可以正常工作,因为您的代码没有歧义,即使它的行为不符合您的要求。但是,您将无法扩展此代码,因为它会导致问题,让我举例说明:

我之前的一个建议如下:

public class Client {
    //...
    public void unknownPacketReceived(Packet pkt) { 
        System.out.println("Unimplemented packet received.");
    }

    public void packetReceived(ClientInformations ci) {

    }

    //...
}

然而,这不能像 ClientInformations 对象一样工作,因为它是一个更复杂的简单 Packet 对象/接口(interface),它会给出以下编译错误:

incompatible types: Packet cannot be converted to ClientInformations

发生这种情况是因为 reference 类型仍然只是 Packet,而您希望将其提升为 ClientInformations

它可以工作,但是如果你将它命名为:

client.receivedPacket((ClientInformations)packet)

这对你的情况没有坏处,因为在运行时它们是相同的类型,所以在转换中不会丢失任何东西,这需要伴随着 instanceof 树,这就是为什么你现在回到了零步。

这个程序只是会起作用,如果你想让它简单,我建议改变你的设计,继续这条路可能是一个选择,如果您正在处理遗留应用程序,不能只是更改内容,但这并不容易。

关于Java方法重载困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20732451/

相关文章:

installation - 如何知道用户在 Swing 面板中选择的 JDK 位版本

java - 检查 REST 方法中是否存在 JSON Key

objective-c - 从父类(super class)的方法实现返回

c# - 继承和基础构造函数

java - Bug JDK-8191002 不清楚是编程错误还是 JRE 错误

java 键盘快捷键捕获对话框

c++ - 无效的协变返回类型(参数也被继承)

asp.net-mvc - WebAPI 模型 [ModelBinder] 具有接口(interface)类,同时指定实现

c# - 如何在接口(interface)上实现静态方法?

c# - 我应该如何确保处理可能是一次性的元素?