2

假设我给自己定义了一种新型的字节流(类似于 OutputStream):

public interface MyByteStream {
    public void write(byte[] data) throws IOException;
}

另外,我有一个可以将字符串写入字节流的辅助类,为了灵活性,我希望有两个版本的方法,以便它可以与常规的 OutputStream 或我的新 MyByteStream 一起使用:

public class StringWriter {
    public void write(String string, MyByteStream stream) throws IOException {
        stream.write(string.getBytes());
    }

    public void write(String string, OutputStream stream) throws IOException {
        stream.write(string.getBytes());
    }
}

现在,如果我有一个扩展 OutputStream实现 MyByteStream 的类,如下所示:

public class DebugStream extends OutputStream implements MyByteStream {
    @Override
    public void write(int b) throws IOException {
        System.out.println(b);
    }
}

我不能像这样调用我的 StringWriter 的 write 方法:

new StringWriter().write("Hello", new DebugStream());

因为它会给我以下错误:

The method write(String, MyByteStream) is ambiguous for the type StringWriter

我可以通过将 DebugStream 显式转换为字节流之一来解决问题,如下所示:

new StringWriter().write("Hello", (OutputStream) new DebugStream());
new StringWriter().write("Hello", (MyByteStream) new DebugStream());

但是由于这两种方法无论如何都做完全相同的事情,我宁愿不必到处都做演员。有没有办法解决这个问题?喜欢将其中一种方法定义为此类模棱两可的调用的首选方法吗?或者也许是一些泛型的诡计?

笔记:

我想保持编译时类型安全性,所以下面的“解决方案”已经出来了:

public class StringWriter {
    public void write(String string, Object stream) throws IOException {
        if (stream instanceof OutputStream) {
            ((OutputStream) stream).write(string.getBytes());
        } else if (stream instanceof MyByteStream) {
            ((MyByteStream) stream).write(string.getBytes());
        } else {
            throw new IllegalArgumentException();
        }
    }
}
4

1 回答 1

1

有两个主要选项:

1)以不同的方式命名方法,而不是重载现有的方法:

public void write(String string, OutputStream stream) {
    //
}

public void writeMyByteStream(String string, MyByteStream stream) {
    //
}

这不是一个好的解决方案,因为它用实现细节污染了 API,但它是一个选项。

2)使用一种公共方法,但私下选择如何处理流类型:

public void write(String string, OutputStream stream) {
    if (stream instanceof MyByteStream) {
        writeMyByteStream(string, stream);
    } else {
        writeOutputStream(string, stream);
    }
}

private void writeMyByteStream(String string, MyByteStream stream) {
    //
}

private void writeOutputStream(String string, OutputStream stream) {
    //
}

更简洁的方法是第二种方法,因为 API 要简单得多,并且客户端不需要知道该类对MyByteStream. 这也意味着以后可以在不更改任何客户端代码的情况下从实现中撤消特殊支持。

有些人可能会instanceof从风格的角度质疑使用,但当你需要它时,你就需要它。

于 2014-06-30T03:42:31.777 回答