簡體   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