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

dod*_*lex 64 java constructor abstract

我有一个定义抽象方法的抽象类A. 这意味着,对于要实现的类,必须实现所有抽象方法.

我希望我的所有子类都实现一个带有2个int作为参数的构造函数.

声明构造函数会破坏我的目的,因为我想要在子类中定义的构造函数,我对实现一无所知.而且我不能将构造函数声明为抽象;

有没有办法做到这一点 ?

我想要的例子:

让我们说我正在定义Matrix类的API.在我的问题中,Matrix无法改变其尺寸.

要创建Matrix,我需要提供它的大小.

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

假设我想invert()在抽象类中提供该方法的基本实现.此方法将创建具有this反转尺寸的新矩阵.更具体地说,正如它在抽象类中定义的那样,它将this使用带有两个整数的构造函数创建同一类的新实例.由于它不知道实例,它将使用反射(getDefinedConstructor),我想要一种方式来保证我会得到它,并且它将对实现有意义.

Jon*_*eet 53

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

而且,正如你所说,你对实现一无所知 - 所以你怎么知道它们适合于拥有一个需要两个整数的构造函数呢?如果其中一个人也需要一个字符串怎么办?或者它可能有意义使用常量作为其中一个整数.

这里的大局是什么 - 为什么要在子类上强制使用特定的构造函数签名?(正如我所说,你实际上无法做到这一点,但如果你解释为什么要这样做,解决方案可能会出现.)

一种选择是为工厂提供单独的界面:

interface MyClassFactory
{
    MyClass newInstance(int x, int y);
}
Run Code Online (Sandbox Code Playgroud)

然后你的每个具体子类MyClass都需要一个知道如何构造给定两个整数的实例的工厂.虽然它并不是非常方便 - 你仍然需要自己构建工厂的实例.再次,这里的真实情况是什么?

  • @dodecaplex,您可以轻松地在抽象类中声明一个构造函数,该构造函数采用两个整数,然后是一个非固定构造函数,用于`FixedSizeMatrix`,它看起来像`public FixedSizeMatrix(){super(10,10); 像乔恩说的那样.API不是关于构造函数(如何构建对象)而是关于方法(如何使用对象). (3认同)
  • 让我们说我正在定义Matrix类的API.在我的问题中,Matrix无法改变其尺寸.要创建Matrix,我需要提供它的大小.因此,我希望我的所有实现者都为构造函数提供大小作为参数.这个构造函数的动机是问题,而不是实现问题.只要保留了方法的所有语义,实现就可以用它们做任何事情. (2认同)

emo*_*ory 6

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

这太傻了.比较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 ) ;
    }
}
Run Code Online (Sandbox Code Playgroud)