有没有办法确保实现接口的类实现静态方法? [英] Is there a way to make sure classes implementing an Interface implement static methods?

查看:28
本文介绍了有没有办法确保实现接口的类实现静态方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我阅读了erickson对为什么我不能在 Java 接口中定义静态方法?".这个问题不是关于为什么",而是关于然后如何?".<小时>我原来的例子是病态的,但我会把它留在下面.

First of all, I read erickson's useful reply to "Why can’t I define a static method in a Java interface?". This question is not about the "why" but about the "how then?".


my original example was ill-posed, but I'll leave it below.

虽然我现在确信在大多数情况下我想做的是矫枉过正,但在一种情况下可能需要这样做:

While I am now convinced that in most cases what I want to do is overkill, there is one scenario where it could be needed:

我将再次以 ParametricFunction 为例.现在让我们采用一个复杂的函数,例如 Bessel 函数,其中适合使用查找表.那必须被初始化,所以这两个选项是将参数直接传递给构造函数或提供一个 init(double[] parameters).后者的缺点是 getValue(double x) 必须在每次调用时检查初始化(或者 ArrayIndexOutOfBoundsException 必须被视为初始化检查),因此对于时间关键的应用程序我更喜欢构造函数方法:

I'll take the ParametricFunction example again. Now let's take a complicated function, like the Bessel functions, where a lookup-table is appropriate. That has to be initialised, so the two options are passing the parameters directly to the constructor or providing a init(double[] parameters). The latter has the disadvantage that getValue(double x) must check the initialisation every call (or the ArrayIndexOutOfBoundsException must be considered as initialisation-check), so for time-critical applications I'd prefer the constructor-method:

interface ParametricFunction {
  public double getValue(double x);
}

class BesselFunction implements ParametricFunction {
  public BesselFunction(double[] parameters) { ... }
  public double getValue(double x) { ... }
}

这就涉及到另一个问题,接口中的构造函数是不可能的.那里有什么好的解决方案?我当然可以使用 init(double[] parameters) 方法,但我提到了我不这样做的原因.(好的,这里一个实现接口的抽象类就可以了)

Which touches another problem, the impossibility of constructors in interfaces. What would be a good solution there? I could of course use the init(double[] parameters) approach, but I mentioned my reason why not.
( OK, here an abstract class implementing the interface would do)

现在让我们假设 ParametricFunction 只允许某些参数,例如正整数.如何检查传递给构造函数的参数的有效性?抛出一个 IllegalArgument 异常是可能的,但是 checkParametersValidity(double[] parameters) 似乎更方便.但是需要在构造之前检查参数,所以它必须是一个静态方法.这就是我真的很想知道一种方法来确保实现 ParametricFunction 接口的每个类确实定义了这个静态方法.

Now let's assume the ParametricFunction allows only certain parameters, e.g. positive integers. How to check the vailidity of parameters passed to the constructor? Throwing an IllegalArgument-exception would be a possibility, but a checkParametersValidity(double[] parameters) seems a lot more convenient. But checking the parameters needs to be done before construction, so it has to be a static method. And that's where I'd really like to know a way to make sure every class implementing the ParametricFunction interface does define this static method.

我知道这个例子很人为,不简单地通过接口使用init方法的原因是有争议的,我仍然想知道答案.如果您不喜欢,请将其视为学术问题.

I know this example is rather artificial, and the reason for not simply using a init method through the interface is debatable, I'd still like to know the answer. Consider it an academic question if you don't like it.

(原始示例)

所以基本上我想要一个接口来提供常用的方法和例如getSimilarObject 方法.对于(一个虚构的)例子

So basically I want one Interface to provide both usual methods and e.g. a getSimilarObject method. For (a made up) example

public interface ParametricFunction {
  /** @return f(x) using the parameters */
  static abstract public double getValue(double x, double[] parameters);

  /** @return The function's name */
  static abstract public String getName();

  /** @return Whether the parameters are valid  [added on edit] */
  static abstract public boolean checkParameters(double[] parameters);
}

然后

public class Parabola implements ParametricFunction {
  /** @return f(x) = parameters[0] * x² + parameters[1] * x + parameters[2] */
  static public double getValue(double x, double[] parameters) {
    return ( parameters[2] + x*(parameters[1] + x*parameters[0]));
  }
  static public String getName() { return "Parabola"; }
  // edit:
  static public boolean checkParameters(double[] parameters) {
    return (parameters.length==3);
  }
}

既然当前的 Java 标准不允许这样做,那么与此最接近的是什么?

Since this is not allowed in the current Java standard, what is the closest thing to this?

这背后的想法是将几个 ParametricFunction 放在一个包中并使用反射将它们全部列出,允许用户选择例如绘制哪一个.显然,可以提供一个包含可用 ParametricFunction 数组的加载器类,但是每次实现一个新的时,都必须记住在那里添加它.

The idea behind this is putting several ParametricFunctions in a package and use Reflection to list them all, allowing the user to pick e.g. which one to plot. Obviously one could provide a loader class containing an array of the available ParametricFunctions, but every time a new one is implemented one has to remember adding it there, too.

调用它的一个例子是

public double evaluate(String fnName, double x, double parameters) throws (a lot) {
  Class<ParametricFunction> c = (Class<ParametricFunction>) ClassLoader.getSystemClassLoader().loadClass(fnName);
  Method m = c.getMethod("getValue", x, parameters);
  return ((double) m.invoke(null));
}

并调用 evaluate("Parabola", 1, new double[]{1,2,0});.

推荐答案

不能要求类通过接口实现特定的静态方法.它在 Java 术语中没有任何意义.接口强制在实现接口的类中存在特定的非静态方法;这就是他们所做的.

You cannot require classes to implement particular static methods through an interface. It just makes no sense in Java terms. Interfaces force the presence of particular non-static methods in the classes that implement the interface; that's what they do.

最简单的方法肯定是使用某种工厂类来生成其他工厂类的实例.是的,这确实意味着您必须记住在添加新实例时使该工厂保持最新状态,但是由于您在进行新实现时所做的第一件事是对其进行测试(您确实对其进行了测试,是吗?)会很快解决这个问题!

The easiest way is definitely to have some sort of factory class that produces instances of the others. Yes, this does mean that you have to remember to keep that factory up to date when you add new instances, but since the first thing you do when you make a new implementation is test it (you do test it, yes?) you'll pick up on that problem very quickly!

这篇关于有没有办法确保实现接口的类实现静态方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆