[英]How to give a child class a modified inherited method?
我面臨着以下問題的最佳OOP設計解決方案的麻煩:我有父抽象類Classifier
,其中包括抽象方法classify(Instances dataset)
。 兩個類擴展了Classifier
,即NormalClassifier
和ThresholdClassifier
。 這兩個子類均實現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:
我上面的示例只是我通常遇到的常見設計問題的示例。 因此,我在尋找通用解決方案而不是特定解決方案。
我可以看到多種解決方案:
使ThresholdClassifier
從NormalClassifier
擴展。
將Classifier
更改為具體類(刪除摘要)。
在ThresholdClassifier
上實現classify(Instances dataset)
classify(Instances dataset, double threshold)
並使用默認threshold
值調用classify(Instances dataset, double threshold)
。
例如:
void classify(Instances dataset) {
classify(dataset, 10);
}
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
可以解釋為一個double
或Double
)。
您也可以考慮將選項顯式設置為String
而不是Object
。 這至少可以使您制作一個通用的命令行驅動程序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.