我如何强制在我的抽象类的所有子类中定义构造函数

我有一个定义抽象方法的抽象类A. 这意味着,对于一个class级来说,这个抽象的方法必须得到执行。

我想我所有的子类实现一个2 int作为参数的构造函数。

声明一个构造函数会破坏我的目的,因为我想在子类中定义构造函数,而且我不知道任何有关实现的信息。 而且我不能声明构造函数是抽象的;

有没有办法做到这一点 ?

我想要的例子:

假设我正在定义Matrix类的API。 在我的问题,matrix不能改变他们的尺寸。

要创buildmatrix,我需要提供它的大小。

因此,我希望我的所有实现者都能提供构造函数的大小作为参数。 这个构造函数是由问题驱动的,而不是由于实现问题。 只要方法的所有语义都保持不变,实现可以用它们做任何事情。

假设我想提供我的抽象类中的invert()方法的基本实现。 这种方法将创build一个新的matrix与this倒转的维度。 更具体地说,就像在抽象类中定义的那样,它将使用一个带有两个整数的构造函数创build一个与此相同类的新实例。 因为它不知道实例将使用reflection(getDefinedConstructor),我想要一个保证,我会得到它的方式,这将是有意义的实现。

你不能在你的子类强制构造函数的特定签名 – 但是你可以强制它在你的抽象类中的构造函数中取两个整数。 例如,子类可以从无参数的构造函数中调用该构造函数,传入常量。 这是最接近你可以来。

而且,正如你所说的,你不知道什么是实现 – 那么你怎么知道他们有一个需要两个整数的构造函数是合适的呢? 如果他们中的一个需要一个string呢? 或者可能对于其中的一个整数使用常量是有意义的。

这里的大图是什么 – 为什么你要在你的子类上强制一个特定的构造函数签名? (正如我所说,你实际上不能这样做 ,但是如果你解释为什么你想要它,一个解决scheme可能会出现。)

一种select是为工厂设置一个单独的界面:

 interface MyClassFactory { MyClass newInstance(int x, int y); } 

那么MyClass每一个具体的子类都需要一个工厂,它知道如何build立一个给定两个整数的实例。 尽pipe这不是非常方便 – 而且你仍然需要自己build立工厂的实例。 再一次,这里的真实情况是什么?

如果您需要在界面中定义实现类将使用的内部表示,那么您只是做错了。 请阅读封装和数据抽象 。

如果您的抽象实现依赖于某些实现细节,那么它们就属于这个抽象类。 也就是说,抽象类应该定义一个构造函数,它允许它初始化允许抽象方法工作所需的内部状态。

通常,构造函数旨在通过提供该对象实例的初始状态的一些细节来创build类的实例。 这并不意味着正在构build的实例应该复制对每个单独参数的引用,这在我看到的大多数软件中通常都是这样。 因此,即使Java确实提供了一个强制在子类上执行特定构造器签名的构造,这些子类也可以很容易地抛弃这些参数。

你可以尝试下面的东西。 如果实现类没有带有适当参数的构造函数,构造函数将抛出exception。

这很愚蠢。 比较OK和Bad。 两个类都是相同的,除了OK满足您的要求并因此通过运行时检查。 因此,执行这一要求促进了反效果的繁忙工作。

更好的解决办法是某种工厂。

 abstract class RequiresConstructor { RequiresConstructor( int x, int y ) throws NoSuchMethodException { super(); System.out.println( this.getClass().getName() ) ; this.getClass(). getConstructor ( int.class , int.class ) ; } public static void main( String[] args ) throws NoSuchMethodException { Good good = new Good ( 0, 0 ); OK ok = new OK (); Bad bad = new Bad (); } } class Good extends RequiresConstructor { public Good( int x, int y ) throws NoSuchMethodException { super( x, y ) ; } } class OK extends RequiresConstructor { public OK( int x, int y ) throws NoSuchMethodException { super( x, y ) ; throw new NoSuchMethodException() ; } public OK() throws NoSuchMethodException { super( 0, 0 ) ; } } class Bad extends RequiresConstructor { public Bad() throws NoSuchMethodException { super( 0, 0 ) ; } } 

有点晚了,但…

只需在你的类中创build一个总是被称为超级构造函数的默认构造函数。 在这个默认的构造函数中,你可以用自己的类对象(这不是抽象的超类而是具体的子类)来检查所有定义的构造函数。 如果您想要实现的构造函数丢失,请抛出一个运行时exception。

我不是一个很好的反思的朋友,因为它有通过后门黑客的味道,但有时它有助于…

看看这个例子:

 import java.lang.reflect.Constructor; public abstract class Gaga { public Gaga() { boolean found = false; try { Constructor<?>[] constructors = getClass().getConstructors(); for (Constructor<?> c : constructors) { if (c.getParameterTypes().length==2) { Class<?> class0 = c.getParameterTypes()[0]; Class<?> class1 = c.getParameterTypes()[1]; if ( (class0.getName().equals("int") || class0.isAssignableFrom(Integer.class)) && (class1.getName().equals("int") || class1.isAssignableFrom(Integer.class)) ) found = true; } } } catch (SecurityException e) { found = false; } if (!found) throw new RuntimeException("Each subclass of Gaga has to implement a constructor with two integers as parameter."); //... } } 

和一个testing课:

 public class Test { private class Gaga1 extends Gaga { public Gaga1() { this(0, 0); } public Gaga1(int x, Integer y) { } } private class Gaga2 extends Gaga { } public static void main(String[] args) { new Gaga1(); new Gaga1(1, 5); new Gaga2(); System.exit(0); } } 

在主函数中将创buildGaga1的对象,但是创buildGaga2会抛出一个运行时exception。

但是你不能确定这个构造函数是否被调用 – 你甚至不能确定它正在做你想要的东西。

这个testing只有在你使用reflection的时候才有用。

抽象类有一个抽象的方法,它将采取你想要的参数。 例如:

 public abstract void setSize(int rows,int columns);