Gibt es eine Möglichkeit sicherzustellen, dass Klassen, die eine Schnittstelle implementieren, statische Methoden implemJava

Java-Forum
Anonymous
 Gibt es eine Möglichkeit sicherzustellen, dass Klassen, die eine Schnittstelle implementieren, statische Methoden implem

Post by Anonymous »

Zuerst habe ich Ericksons nützliche Antwort auf „Warum kann ich keine statische Methode in einer Java-Schnittstelle definieren?“ gelesen. Bei dieser Frage geht es nicht um das „Warum“, sondern um das „Wie dann?“.

Bearbeiten: Mein ursprüngliches Beispiel war schlecht formuliert, aber ich belasse es weiter unten.

Während ich jetzt davon überzeugt bin, dass das, was ich tun möchte, in den meisten Fällen übertrieben ist, gibt es ein Szenario, in dem es nötig sein könnte:

Ich nehme noch einmal das ParametricFunction-Beispiel. Nehmen wir nun eine komplizierte Funktion wie die Bessel-Funktionen, bei der eine Nachschlagetabelle geeignet ist. Das muss initialisiert werden, daher bestehen die beiden Optionen darin, die Parameter direkt an den Konstruktor zu übergeben oder einen init(double[]-Parameter) bereitzustellen. Letzteres hat den Nachteil, dass getValue(double x) bei jedem Aufruf die Initialisierung überprüfen muss (oder die ArrayIndexOutOfBoundsException als Initialisierungsprüfung berücksichtigt werden muss), daher würde ich für zeitkritische Anwendungen den Konstruktor bevorzugen -Methode:

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

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


Was ein weiteres Problem berührt, nämlich die Unmöglichkeit von Konstruktoren in Schnittstellen. Was wäre da eine gute Lösung? Ich könnte natürlich den init(double[]-Parameter)-Ansatz verwenden, aber ich habe meinen Grund genannt, warum nicht.

(Edit: OK, hier würde eine abstrakte Klasse, die die Schnittstelle implementiert, genügen)

Nehmen wir nun an, dass die ParametricFunction nur bestimmte Parameter zulässt, z.B. positive ganze Zahlen. Wie überprüfe ich die Gültigkeit der an den Konstruktor übergebenen Parameter? Das Auslösen einer IllegalArgument-Ausnahme wäre eine Möglichkeit, aber ein checkParametersValidity(double[] Parameters) scheint viel praktischer zu sein. Die Überprüfung der Parameter muss jedoch vor der Konstruktion erfolgen, daher muss es sich um eine statische Methode handeln. Und hier würde ich wirklich gerne wissen, wie ich sicherstellen kann, dass jede Klasse, die die ParametricFunction-Schnittstelle implementiert, diese statische Methode definiert.

Ich kenne dieses Beispiel ist eher künstlich, und der Grund dafür, nicht einfach eine init-Methode über die Schnittstelle zu verwenden, ist umstritten, ich würde trotzdem gerne die Antwort wissen. Betrachten Sie es als eine akademische Frage, wenn sie Ihnen nicht gefällt.

(Originalbeispiel)

Im Grunde möchte ich also, dass eine Schnittstelle sowohl die üblichen Methoden als auch z.B. eine getSimilarObject-Methode. Als (ein erfundenes) Beispiel

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);
}


und dann

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);
}
}


Da dies im aktuellen Java-Standard nicht zulässig ist, was kommt dem am nächsten?

Die Die Idee dahinter besteht darin, mehrere ParametricFunctions in ein Paket zu packen und Reflection zu verwenden, um sie alle aufzulisten, sodass der Benutzer z. welches man planen soll. Natürlich könnte man eine Loader-Klasse bereitstellen, die ein Array der verfügbaren ParametricFunctions enthält, aber jedes Mal, wenn eine neue implementiert wird, muss man daran denken, sie auch dort hinzuzufügen.

Bearbeiten: Ein Beispiel dafür ist

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


und den Aufruf von „evaluate("Parabola", 1, new double[]{1,2,0});.

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post