[英]How to give a child class a modified inherited method?
I'm facing a trouble finding the best OOP design solution to the following problem: I have the parent abstract class Classifier
which includes the abstract method classify(Instances dataset)
. 我面临着以下问题的最佳OOP设计解决方案的麻烦:我有父抽象类
Classifier
,其中包括抽象方法classify(Instances dataset)
。 Two classes extends Classifier
, namely NormalClassifier
and ThresholdClassifier
. 两个类扩展了
Classifier
,即NormalClassifier
和ThresholdClassifier
。 Both the children classes implements the classify(Instances dataset)
method. 这两个子类均实现
classify(Instances dataset)
方法。 However, ThresholdClassifier
requires the classify(Instances dataset)
method to be of this form classify(Instances dataset, double threshold)
and can't never work with classify(Instances dataset)
. 但是,
ThresholdClassifier
要求classify(Instances dataset)
方法具有这种形式classify(Instances dataset, double threshold)
并且永远不能与classify(Instances dataset)
。
Note that ThresholdClassifier
can't accept the threshold
parameter in its constructor and it must have the parameters in the classify
method. 请注意,
ThresholdClassifier
不能在其构造函数中接受threshold
参数,并且必须在classify
方法中具有该参数。
In this case the child class ThresholdClassifier
share the same characteristic as the parent but it requires a different method signature. 在这种情况下,子类
ThresholdClassifier
与父类具有相同的特征,但是需要不同的方法签名。 I'm not able to extend the parent class because it would require me to implement the original method signature nor it makes sense not to extend the parent class because it's clearly a Classifier
. 我无法扩展父类,因为这将要求我实现原始方法签名,也不能扩展父类,因为它显然是
Classifier
这是没有道理的。 So how would one solve such a design problem in Java OOP? 那么如何解决Java OOP中的这种设计问题呢? Is there a technical term for this issue?
这个问题有技术术语吗?
Edit 1: 编辑1:
what I basically did to solve this issue is that I created an interface called ThresholdBasedClassifier
that contains the method setThreshold(double threshold)
. 解决此问题的基本方法是创建一个名为
ThresholdBasedClassifier
的接口,其中包含方法setThreshold(double threshold)
。 Then I made ThresholdClassifier
implement this method and created an internal field called threshold
. 然后,我使
ThresholdClassifier
实现此方法,并创建了一个称为threshold
的内部字段。 However, I find this to be an ugly design solution for many reasons, especially that the user could forget that he needs to set change or set the threshold before calling classify(Instances dataset)
但是,由于许多原因,我发现这是一个丑陋的设计解决方案,尤其是用户可能忘记了自己需要在调用
classify(Instances dataset)
之前设置更改或设置阈值
Edit 2: 编辑2:
Also the requirements says that there can't be a default value for the threshold
. 此外,要求还指出,
threshold
值不能有默认值。
Edit 3: 编辑3:
My example above was just an example to a common design problem I'm facing in general. 我上面的示例只是我通常遇到的常见设计问题的示例。 So I'm looking for a general solution not a specific solution.
因此,我在寻找通用解决方案而不是特定解决方案。
I can see multiple solutions: 我可以看到多种解决方案:
Make ThresholdClassifier
extends from NormalClassifier
. 使
ThresholdClassifier
从NormalClassifier
扩展。
Change Classifier
to a concrete class (remove abstract). 将
Classifier
更改为具体类(删除摘要)。
Implement classify(Instances dataset)
on ThresholdClassifier
calling the classify(Instances dataset, double threshold)
with a default threshold
value. 在
ThresholdClassifier
上实现classify(Instances dataset)
classify(Instances dataset, double threshold)
并使用默认threshold
值调用classify(Instances dataset, double threshold)
。
For example: 例如:
void classify(Instances dataset) {
classify(dataset, 10);
}
Classifier
, so each one overrides the apropriate one: Classifier
上创建两个空方法,因此每个方法都会覆盖适当的方法: Code: 码:
public abstract class Classifier {
void classify(Instances dataset) {
}
void classify(Instances dataset, double threshold) {
}
}
public class NormalClassifier extends Classifier {
void classify(Instances dataset) {
// Code here
}
}
public class ThresholdClassifier extends Classifier {
void classify(Instances dataset, double threshold) {
// Code here
}
}
You can even throw an exception inside Classifier methods. 您甚至可以在Classifier方法内引发异常。 This will enforce the implementation on the child class.
这将在子类上强制实施。
As ThresholdClassifier
"can't never work with classify(Instances dataset)
", I think this method shouldn't be declared in Classifier
abstract class. 由于
ThresholdClassifier
“永远无法使用classify(Instances dataset)
”,我认为不应在Classifier
抽象类中声明此方法。 You should remove classify
method from Classifier
and declare classify(Instances dataset)
in NormalClassifier
and classify(Instances dataset, double threshold)
in ThresholdClassifier
. 您应从
Classifier
删除classify
方法,并在NormalClassifier
声明classify(Instances dataset)
,并在ThresholdClassifier
声明classify(Instances dataset)
classify(Instances dataset, double threshold)
。
ThresholdClassifier
should contain an internal value double threshold
which allows it to define: ThresholdClassifier
应该包含一个内部值double threshold
,该double threshold
允许它定义:
private double threshold = DEF_THRESHOLD;
public void setThreshold(final double threshold){
this.threshold = threshold;
}
@Override
public void classify(Instances dataset){
this.classify(dataset, threshold);
}
private void classify(Instances dataset, final double threshold){
// TODO implement this classify method
}
Additional Info 附加信息
Are you asking for a general signature? 您是否要求一般签名? Which I think is worthless because it means that for each different type there will be different interfaces which means you won't get very much reuse out of defining it this way which completely defeats the purpose of using a class hierarchy, interfaces, and abstract classes.
我认为这毫无用处,因为这意味着对于每种不同的类型,都会有不同的接口,这意味着通过这种方式定义它不会有太多重用,这完全破坏了使用类层次结构,接口和抽象类的目的。 Nevertheless there are such methods in Java.
尽管如此,Java中还是有这样的方法。 You would need something like the following:
您将需要以下内容:
public abstract void classify(final Instances dataset,
final Object... options) throws IllegalArgumentException
Then your ThresholdClassifier
would look something like this: 然后您的
ThresholdClassifier
看起来像这样:
public ThresholdClassifier extends Classifier{
@Override
public void classify(final Instances dataset,
final Object... opts) throws IllegalArgumentException {
if(opts.length != 1)
throw new IllegalArgumentException(); // probably should say something
try{
// casts from Double to double automatically
final double threshold = (Double)opts[0];
// TODO implement classify method
// ...
}catch(ClassCastException cce){
throw new IllegalArgumentException();// should probably say something
}
You may be able to make the above an abstract class and require a method void classify(final Instances dataset, final double threshold)
(I'm not totally sure--it may be considered ambiguous since the double threshold
could be interpreted as either a double
or a Double
). 您可能可以将上面的内容做成一个抽象类,并需要一个方法
void classify(final Instances dataset, final double threshold)
(我不太确定,由于double threshold
可以解释为一个double
或Double
)。
You may also consider making the options explicitly be String
instead of Object
. 您也可以考虑将选项显式设置为
String
而不是Object
。 This at least would allow you to make a general command line driver. 这至少可以使您制作一个通用的命令行驱动程序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.