繁体   English   中英

如何给子类一个修改后的继承方法?

[英]How to give a child class a modified inherited method?

我面临着以下问题的最佳OOP设计解决方案的麻烦:我有父抽象类Classifier ,其中包括抽象方法classify(Instances dataset) 两个类扩展了Classifier ,即NormalClassifierThresholdClassifier 这两个子类均实现classify(Instances dataset)方法。 但是, ThresholdClassifier要求classify(Instances dataset)方法具有这种形式classify(Instances dataset, double threshold)并且永远不能与classify(Instances dataset)

请注意, ThresholdClassifier不能在其构造函数中接受threshold参数,并且必须在classify方法中具有该参数。

在这种情况下,子类ThresholdClassifier与父类具有相同的特征,但是需要不同的方法签名。 我无法扩展父类,因为这将要求我实现原始方法签名,也不能扩展父类,因为它显然是Classifier这是没有道理的。 那么如何解决Java OOP中的这种设计问题呢? 这个问题有技术术语吗?

编辑1:

解决此问题的基本方法是创建一个名为ThresholdBasedClassifier的接口,其中包含方法setThreshold(double threshold) 然后,我使ThresholdClassifier实现此方法,并创建了一个称为threshold的内部字段。 但是,由于许多原因,我发现这是一个丑陋的设计解决方案,尤其是用户可能忘记了自己需要在调用classify(Instances dataset)之前设置更改或设置阈值

编辑2:

此外,要求还指出, threshold值不能有默认值。

编辑3:

我上面的示例只是我通常遇到的常见设计问题的示例。 因此,我在寻找通用解决方案而不是特定解决方案。

我可以看到多种解决方案:

  1. 使ThresholdClassifierNormalClassifier扩展。

  2. Classifier更改为具体类(删除摘要)。

  3. ThresholdClassifier上实现classify(Instances dataset) classify(Instances dataset, double threshold)并使用默认threshold值调用classify(Instances dataset, double threshold)

例如:

void classify(Instances dataset) {
    classify(dataset, 10);
}
  1. Classifier上创建两个空方法,因此每个方法都会覆盖适当的方法:

码:

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

您甚至可以在Classifier方法内引发异常。 这将在子类上强制实施。

由于ThresholdClassifier “永远无法使用classify(Instances dataset) ”,我认为不应在Classifier抽象类中声明此方法。 您应从Classifier删除classify方法,并在NormalClassifier声明classify(Instances dataset) ,并在ThresholdClassifier声明classify(Instances dataset) classify(Instances dataset, double threshold)

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
}

附加信息

您是否要求一般签名? 我认为这毫无用处,因为这意味着对于每种不同的类型,都会有不同的接口,这意味着通过这种方式定义它不会有太多重用,这完全破坏了使用类层次结构,接口和抽象类的目的。 尽管如此,Java中还是有这样的方法。 您将需要以下内容:

public abstract void classify(final Instances dataset, 
    final Object... options) throws IllegalArgumentException

然后您的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
    }

您可能可以将上面的内容做成一个抽象类,并需要一个方法void classify(final Instances dataset, final double threshold) (我不太确定,由于double threshold可以解释为一个doubleDouble )。

您也可以考虑将选项显式设置为String而不是Object 这至少可以使您制作一个通用的命令行驱动程序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM