静态方法中的重复代码
Duplicate code in static methods
我在 JAVA 中实现了两个阅读器。见下文:
public final class ReaderA {
public ReaderA() {}
public static int read(final File file) {
final byte[] data = Files.readAllbytes(file.toPath());
return read(data);
}
public static int read(final byte[] data) {
// do somethingA
}
...// and some other methods
}
public final class ReaderB {
public ReaderB() {}
// this method is exactly the same as in ReaderA
public static int read(final File file) {
final byte[] data = Files.readAllbytes(file.toPath());
return read(data);
}
// this is implemented different from the one in ReaderA
public static int read(final byte[] data) {
// do somethingB
}
...// and the same other methods as in ReaderA
}
问题。避免重复代码的最佳方法是什么?
我试图在新的摘要 class Reader
中提取重复代码,并尝试制作 read(final byte[] data)
摘要并在 subclasses ReaderA
和 ReaderB
。它不会工作,因为这些方法是静态的。
我认为您首先需要问自己几个问题:
- 我真的需要两个静态方法吗?
- 'methods' 或 class 的通用代码是什么?
- 是否可以制作一个抽象class来编写这样的实现并让 ReaderA 和 ReaderB 扩展它,减少重复代码?
- 你是否应该有一个父 class 然后创建 class 从上面继承的元素?
我认为您应该阅读 SOLID 原则,特别是 Open/Closed 原则和依赖倒置
如果您使用的是 Java SE 8,您可以将静态方法放在接口中。 Java 接口静态方法类似于默认方法,只是我们不能在实现中覆盖它们类。如果实施不当,此功能可帮助我们避免出现不良结果 类.
有几种可能性:
- 从其中一个 class 中删除该方法并使用继承(您不能为静态方法调用 super.myMethod(),但除非您覆盖它,否则它会起作用)
我不建议这样做:您可能会在子 class 中获得其他可用的方法,而您可能不想这样做。
将它提取到一个通用的超级class,用于classes
从一个 class 调用另一个方法。如果它们都保持相同的功能,这将起作用
我不确定用静态方法保留此实现是否是您能做的最好的,但如果是这样,您可以添加一个 Function
参数。
public class Reader {
public static int read(final File file, Function<byte[], Integer> reader) {
final byte[] data = Files.readAllbytes(file.toPath());
return reader.apply(data);
}
}
然后像这样使用它:
public final class ReaderA {
public static int read(final File file) {
return Reader.read(file, ReaderA::read);
}
public static int read(final byte[] data) {
// do somethingA
}
}
自从Java8中引入functional interfaces and method references以来,几乎没有无法避免的重复代码部分。
除非您从 read(byte[])
中删除 static
修饰符并创建实例,否则您将无法使用继承来帮助您。
static
方法的行为不像实例方法,不能被覆盖。相反,super class 和 sub class 都有单独的方法,需要使用 class 名称进行限定。上拉read(File)
表示总是调用超class的read(byte[])
。您仍然必须将 read(File)
复制到每个子 class 以使其使用 class 自己的 read(byte[])
。 中的代码也显示了这一点。
作为参考,请阅读这个问题及其答案:Are static methods inherited in Java?
为了说明:您拥有的两个 read(File)
方法是 而不是 "exactly the same",正如您在代码片段中所说的那样。他们不会同时调用 this.read(data)
,而是分别调用 ReaderA.read(data)
和 ReaderB.read(data)
。查看 read(byte[])
调用如何调用两个完全不同的、不可覆盖的方法。
如果您有能力,我建议您以一种不太静态的方式重写读者:
interface Reader
{
default int read(File file)
{
final byte[] data = Files.readAllbytes(file.toPath());
return read(data);
}
int read(byte[] data);
}
class ReaderA
implements Reader
{
int read(byte[] data)
{
// do somethingA
}
}
class ReaderB
implements Reader
{
int read(byte[] data)
{
// do somethingB
}
}
请注意 read(File)
现在对于所有实施的 class 都是一样的。当然,您必须将调用方法的方式从 ReaderX.read()
更改为 new ReaderX().read()
.
我在 JAVA 中实现了两个阅读器。见下文:
public final class ReaderA {
public ReaderA() {}
public static int read(final File file) {
final byte[] data = Files.readAllbytes(file.toPath());
return read(data);
}
public static int read(final byte[] data) {
// do somethingA
}
...// and some other methods
}
public final class ReaderB {
public ReaderB() {}
// this method is exactly the same as in ReaderA
public static int read(final File file) {
final byte[] data = Files.readAllbytes(file.toPath());
return read(data);
}
// this is implemented different from the one in ReaderA
public static int read(final byte[] data) {
// do somethingB
}
...// and the same other methods as in ReaderA
}
问题。避免重复代码的最佳方法是什么?
我试图在新的摘要 class Reader
中提取重复代码,并尝试制作 read(final byte[] data)
摘要并在 subclasses ReaderA
和 ReaderB
。它不会工作,因为这些方法是静态的。
我认为您首先需要问自己几个问题:
- 我真的需要两个静态方法吗?
- 'methods' 或 class 的通用代码是什么?
- 是否可以制作一个抽象class来编写这样的实现并让 ReaderA 和 ReaderB 扩展它,减少重复代码?
- 你是否应该有一个父 class 然后创建 class 从上面继承的元素?
我认为您应该阅读 SOLID 原则,特别是 Open/Closed 原则和依赖倒置
如果您使用的是 Java SE 8,您可以将静态方法放在接口中。 Java 接口静态方法类似于默认方法,只是我们不能在实现中覆盖它们类。如果实施不当,此功能可帮助我们避免出现不良结果 类.
有几种可能性:
- 从其中一个 class 中删除该方法并使用继承(您不能为静态方法调用 super.myMethod(),但除非您覆盖它,否则它会起作用)
我不建议这样做:您可能会在子 class 中获得其他可用的方法,而您可能不想这样做。
将它提取到一个通用的超级class,用于classes
从一个 class 调用另一个方法。如果它们都保持相同的功能,这将起作用
我不确定用静态方法保留此实现是否是您能做的最好的,但如果是这样,您可以添加一个 Function
参数。
public class Reader {
public static int read(final File file, Function<byte[], Integer> reader) {
final byte[] data = Files.readAllbytes(file.toPath());
return reader.apply(data);
}
}
然后像这样使用它:
public final class ReaderA {
public static int read(final File file) {
return Reader.read(file, ReaderA::read);
}
public static int read(final byte[] data) {
// do somethingA
}
}
自从Java8中引入functional interfaces and method references以来,几乎没有无法避免的重复代码部分。
除非您从 read(byte[])
中删除 static
修饰符并创建实例,否则您将无法使用继承来帮助您。
static
方法的行为不像实例方法,不能被覆盖。相反,super class 和 sub class 都有单独的方法,需要使用 class 名称进行限定。上拉read(File)
表示总是调用超class的read(byte[])
。您仍然必须将 read(File)
复制到每个子 class 以使其使用 class 自己的 read(byte[])
。
作为参考,请阅读这个问题及其答案:Are static methods inherited in Java?
为了说明:您拥有的两个 read(File)
方法是 而不是 "exactly the same",正如您在代码片段中所说的那样。他们不会同时调用 this.read(data)
,而是分别调用 ReaderA.read(data)
和 ReaderB.read(data)
。查看 read(byte[])
调用如何调用两个完全不同的、不可覆盖的方法。
如果您有能力,我建议您以一种不太静态的方式重写读者:
interface Reader
{
default int read(File file)
{
final byte[] data = Files.readAllbytes(file.toPath());
return read(data);
}
int read(byte[] data);
}
class ReaderA
implements Reader
{
int read(byte[] data)
{
// do somethingA
}
}
class ReaderB
implements Reader
{
int read(byte[] data)
{
// do somethingB
}
}
请注意 read(File)
现在对于所有实施的 class 都是一样的。当然,您必须将调用方法的方式从 ReaderX.read()
更改为 new ReaderX().read()
.