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

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

问题描述

首先,我阅读了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 再次举例。现在让我们来看一个复杂的功能,比如贝塞尔函数,其中查找表是合适的。这必须初始化,因此两个选项是将参数直接传递给构造函数或提供 init(double []参数)。后者的缺点是 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 []参数)方法,但我之所以提到我的原因。
(编辑:好的,这里有一个实现接口的抽象类会这样做)

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 -exception是可能的,但 checkParametersValidity(double []参数)似乎更方便。但是在构造之前需要检查参数,因此它必须是静态方法。这就是我真正想知道的方法,以确保实现 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.

编辑:调用它的一个例子是

edit: An example to call it is

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天全站免登陆