2017-01-13 38 views
0

我有一個類層次結構是這樣的:如何在c#中使用泛型時運行子類的overriden方法?

public abstract class BaseObject { 
     //even though this does not have abstract methods I declare it as abstract because I do not want it to be initialized 
     .... 
     public void save(Connection con) { 
      con.InsertOrReplace(this); 
     } 
     .... 
    } 

    public abstract CheckedDataObject : BaseDataObject { 
     .... 
     public abstract new void save(Connection con); 
    } 

這兩個類是由我的數據對象使用,其中一些只需要保存,另一些則在保存之前運行檢查,因爲檢查是在不同的CheckedDataObject保存方法是抽象的

例如:

public class Father : BaseDataObject { 

} 

這只是需要保存,BaseDataObject的保存工作正常,但:

public class Child : CheckedDataObject { 
    .... 
    public override void save(Connection con) { 
     //do checks here to see if it is correct, if not throw an exception 
     con.Insert(this); 
    } 
    .... 


} 

我的問題是,當我使用一個通用的方法來保存這樣的對象的列表(有些可能是父親,有些可能是小孩):

public void save_all<T>(Connection con, List<T> items) where T: BaseDataObject { 
    foreach (int idx = items.Count - 1 ; i >= 0 ; i--) { 
     //initializations and checks go here 
     items[i].save(con); 
    } 
} 

的問題是,保存()總是調用BaseDataObject的保存,即使被解析的項目是CheckedDataObject

如何更改我的方法,以便它將調用正確的保存方法?

預先感謝任何幫助,您可以提供

+1

「BaseDataObject」在哪裏?或者'BaseObject'有拼寫錯誤?修復。 –

+2

違反[Liskov替代原則](https://en.wikipedia.org/wiki/Liskov_substitution_principle)的好例子。 – Fabio

+2

爲什麼你不只是讓基礎類中的虛擬保存允許人們覆蓋它呢?你的問題的標題表明,也許這就是你想要做的 - 你說話,就好像你已經覆蓋了方法,而不是創建一個全新的,這實際上你看起來已經完成了... – Chris

回答

3

入住這https://blogs.msdn.microsoft.com/csharpfaq/2004/03/12/whats-the-difference-between-override-and-new/

我猜你的問題來自於你在使用CheckedDataObject.Savenew點,所以當你迭代和你的條件是被調用的方法將總是BaseObject.save或它的覆蓋。

嘗試在CheckedDataObject

+0

耶是更換新在我的測試項目上工作,比我發現的解決方案更清潔,非常感謝 – Cruces

+1

@Juan這是他們的第44個問題,我認爲他們知道這是如何工作的。 – CodeCaster

+0

@CodeCaster我想你是指「他」和「他」,而不是「他們」和「他們」。無論如何,說這是因爲他發現它是有效的,他忘了這麼做。問候! –

0

使用override代替new我覺得你想找的是一個簡單的基類,像這樣一個虛擬的方法:

public abstract class BaseObject 
    { 
    public virtual void Save(Connection con) 
    { 
     con.InsertOrReplace(this); 
    } 
    } 

    public class Father : BaseObject 
    { 
     public override void Save() 
     { 
     // no checks needed? 
     base.Save(); 
     } 
    } 

    public class Child : BaseObject 
    { 
    public override void Save() 
    { 
    //do checks here to see if it is correct, if not throw an exception 
    base.Save(); 
    } 
    } 

什麼用的CheckedDataObject?我沒看到它。

如果您現在收集了BaseObject並調用Save方法,則將調用派生類的重寫方法。

+0

不,這不起作用,BaseDataObject和CheckedDataObject都具有屬於它們的屬性和方法,I只是在他們的位置寫了點,我認爲這意味着「這裏還有其他的東西」,對不起,如果我不清楚 – Cruces

-1

所以,有一個簡單的解決方案:轉換爲CheckedDataObject。但如果我是你,我寧願避免使用這個類的層次結構。

public void save_all<T>(Connection con, List<T> items) where T: BaseDataObject { 
foreach (int idx = items.Count - 1 ; i >= 0 ; i--) { 
    //initializations and checks go here 
    var cdo = items[i] as CheckedDataObject; 
    if (cdo != null) 
     cdo.save(con); 
    else 
     items[i].save(con); 
}} 
+0

這是類似於我做的,** if(item [i]是CheckedDataObject){( (CheckedDataObject)(對象)項[I])保存(CON)。 } else {items [i] .save(con); } **我只是在尋找一種更好的方式,抱歉沒有提到前面提到 – Cruces

0

要回答你的問題,在基類virtual不使用new,使用override,並聲明函數。

public abstract class BaseObject { 
     //even though this does not have abstract methods I declare it as abstract because I do not want it to be initialized 
     .... 
     public virtual void save(Connection con) { 
      con.InsertOrReplace(this); 
     } 
     .... } 

    public abstract CheckedDataObject : BaseDataObject { 
     .... 
     public override void save(Connection con); } 

其次,也許你應該使用接口而不是抽象類?

三,是BaseObject som那種模式?如果是這樣,也許你會將保存在其他(例如存儲庫)類中。 (Single responsibility principle)。

+0

沒有我只是忽略了很多BaseDataObject應該在那裏的代碼,屬性和方法,這就是爲什麼我用抽象類去的原因,感謝回覆 – Cruces

相關問題