我有一个抽象类A,它定义了抽象方法,这意味着,对于一个可示例化的类,所有的抽象方法都必须被实现。
我希望我所有的子类都能实现一个以2个int为参数的构造函数。
声明一个构造函数违背了我的初衷,因为我希望构造函数定义在子类中,而我对实现一无所知,而且我不能声明一个构造函数是抽象的;
有什么办法吗?
- 我想要的示例:**
假设我正在定义一个Matrix类的API,在我的问题中,Matrix不能改变它们的维数。
对于要创建的矩阵,我需要提供它的大小。
因此,我希望我所有的实现者都给构造函数提供一个参数,这个构造函数是由问题而不是实现所驱动的,只要方法的所有语义都保持不变,实现就可以对这些构造函数做任何事情。
假设我想在抽象类中提供一个invert()
方法的基本实现,这个方法将创建一个新的矩阵,其维数为this
,更具体地说,由于它是在抽象类中定义的,它将创建一个与this
相同的类的新示例。使用一个构造函数,它接受两个整型。因为它不知道示例,所以它将使用反射(getDefinedConstructor),我需要一种方法来保证我将得到它,并且它对实现有意义。
7条答案
按热度按时间falq053o1#
你不能强迫子类中的构造函数有一个特定的签名--但是你可以强迫它通过抽象类中的一个构造函数来获取两个整数。子类可以从一个无参数的构造函数调用那个构造函数,比如传递常量。这是你能做到的最接近的了。
此外,正如你所说,你对实现一无所知--那么你怎么知道他们有一个需要两个整数的构造函数是合适的呢?如果其中一个也需要一个String呢?或者可能对其中一个整数使用一个常量是有意义的。
这里更重要的是什么-- * 为什么 * 要在子类上强制一个特定的构造函数签名呢?(正如我所说,实际上你不能 * 这样做 *,但是如果你解释了为什么要这样做,一个解决方案可能会出现)。
一种选择是为工厂提供单独的接口:
那么
MyClass
的每个具体子类都需要一个工厂,它知道如何在给定两个整数的情况下构建一个示例。尽管这不是很方便--而且你仍然需要构建工厂本身的示例。再问一次,这里的真实的情况是什么?u1ehiz5o2#
你可以尝试下面的方法。如果实现类没有一个带合适参数的构造函数,构造函数将抛出一个异常。
这很愚蠢。比较OK和Bad。这两个类是相同的,除了OK满足你的要求,因此通过了运行时检查。因此,强制要求促进了适得其反的忙碌工作。
一个更好的解决方案是某种工厂。
vlurs2pr3#
如果你需要在你的接口中定义实现类将要使用的内部表示,那么你只是做错了。请阅读关于封装和数据抽象的内容。
如果你的抽象实现依赖于特定的实现细节,那么它们就属于那个抽象类,也就是说,抽象类应该定义一个构造函数,允许它初始化内部状态,以使抽象方法能够工作。
一般来说,构造函数是用来通过提供对象示例初始状态的一些细节来创建类的示例的。这并不意味着被构造的示例应该复制对每个参数的引用,这在我看到的大多数软件中是常见的。因此,即使Java确实提供了一个构造函数来强制在子类上实现某些构造函数签名,那些子类可以容易地丢弃参数。
jdgnovmf4#
有点晚了,但是...
只需在类中创建一个默认构造函数,它总是被称为超构造函数。在这个默认构造函数中,你可以检查所有定义的构造函数,并在它自己的类对象上进行反射(这样就不是抽象超类,而是具体子类)。如果你想要实现的构造函数丢失,抛出一个运行时异常。
我不是一个很好的朋友反思,因为它有黑客通过后门的味道,但有时它帮助...
请看这个例子:
和一个测试类:
在main函数中,Gaga1的对象将被创建,但是Gaga2的创建将抛出运行时异常。
但是您不能确定是否调用了这个构造函数--您甚至不能确定它正在执行您想要的操作。
这个测试只有在使用反射时才有用。
gywdnpxw5#
晚餐:
}
子类:
jtw3ybtb6#
您可以选择APT处理器
免责声明:
关键是我需要这样使用它
和类
和用法
其中,
Backup
和GoodsPrices
是从AbstractQueryProvider
导出的当我忘记这样的构造函数时,我需要编译时错误
因此,对于APT处理器,您将拥有如下类:
(包:"pl. selvin. constructorsconstraints. apt"),带有如下注解:
处理器是这样的:
如果派生类没有这样的构造函数,则会引发编译时错误
可能出现的问题:
Github页面:https://github.com/SelvinPL/ConstructorsConstraints
qni6mghb7#
让抽象类有一个抽象方法,它接受你想要的参数,例如: