2011-09-22 57 views
1

我創建這些類:如何調用派生類虛擬方法?

public abstract class Node 
{ 
    public virtual NodeModel CreateModel() 
    { 
     throw new NotImplementedException(); 
    } 
} 

public class Folder : Node 
{ 
    public virtual FolderModel CreateModel() 
    { 
     // Implementation 
    } 
} 

public class Item : Node 
{ 
    public virtual ItemModel CreateModel() 
    { 
     // Implementation 
    } 
} 

然後在我的節目,我有節點的名單隻包含項目和文件夾對象。當我在列表中循環並嘗試調用CreateModel()方法時,這總是調用的Node類方法(因此拋出異常)。

我不能將CreateModel()更改爲抽象,因爲返回類型根據派生類型而不同。我想知道是否有可能有不同的返回類型。我也想避免泛型。事實是,Intellisense在玩弄它的一個實例時向我展示了上層的方法。如果我從上層類中刪除虛擬實現,那麼它將顯示基類實現。這是我認爲它實際上可能的地方。

那麼我該如何強制程序調用上層類的方法呢?


編輯:答案竟是簡單而正確的在我的鼻子了。返回類型無關緊要,因爲它將從基類AbstractModel()中定義的返回類型繼承。我只是在我的基類中將該方法標記爲抽象,並且它工作得很好。我不知道爲什麼我會在某些時候感到困惑,因爲現在看來我很明顯。

謝謝大家幫助我。

+1

用「上」,你的意思是基類(即節點)或子類/派生類(項或文件夾)。請更新您的問題,因爲它有點不清楚... –

+0

感謝您指出這個錯誤。 – Ucodia

+0

C#不能根據返回類型進行方法解析,所以(除非你像Jon Skeet所建議的那樣使用泛型)我想你會被迫返回一個對象:'public virtual object CreateModel()' –

回答

1

C#不支持covariance函數的返回類型。

無論如何,當其他部件依賴它們更具體時,您只需要指定CreateModel()的返回類型爲NodeModel以外的其他部件。當FolderModel用更多的方法擴展NodeModel時。

如果您只遍歷Node對象列表並調用CreateModel(),則不需要使用NodeModel返回類型聲明Folder.CreateModel(),即使它返回FolderModel。

+0

你的答案發現我錯過了什麼。返回類型無關緊要,因爲FolderModel繼承自NodeModel。我只是在基類中聲明瞭這個函數爲抽象的,它只是按預期工作。非常感謝你和其他人:) – Ucodia

2

它看起來像我的基類應該是通用的,派生類指定適當的類型參數。

public abstract class Node<T> where T : NodeModel 
{ 
    public abstract T CreateModel(); 
} 

public class Folder : Node<FolderModel> 
{ 
    public override FolderModel CreateModel() 
    { 
     // Implementation 
    } 
} 

public class Item : Node<ItemModel> 
{ 
    public override ItemModel CreateModel() 
    { 
     // Implementation 
    } 
} 

現在你有一個方法,適當地覆蓋 - 而不是方法隱藏它總是會得到令人困惑。

編輯:如果你希望能夠把這些沒有泛型,你總是可以創建一個非通用接口,這樣的:

public interface INode 
{ 
    NodeModel CreateModel(); 
} 

public abstract class Node<T> : INode where T : NodeModel 
{ 
    public abstract T CreateModel(); 

    // Explicit interface implementation so we can implement INode.CreateModel 
    // with a different return type. Just delegate to the strongly-typed method. 
    NodeModel INode.CreateModel() 
    { 
     return CreateModle(); 
    } 
} 
+0

是的,我應該精確的我想避免仿製藥出於某種原因,對於僞造這些細節感到抱歉。我大部分時間都在使用它們,但在這些特殊情況下,我的類可能會有許多方面的派生,這會增加太多的複雜性。但是,如果沒有其他辦法,我可能會回到這個想法。謝謝。 – Ucodia

+0

@Ucodia:我強烈懷疑你會發現這會比使用隱藏方法增加*更少的複雜性。將編輯另一個建議... –

+0

是的我知道這是正確的方式,但我的節點實施這裏是不完整的,這是問題將發現。現在看來,我將不得不使用泛型,但我會等待一些更多的反應。 – Ucodia

0

這裏就是類的繼承使用仿製藥,而不是一個版本:

public abstract class Node 
{ 
    public virtual NodeModel CreateModel() 
    { 
     throw new NotImplementedException(); 
    } 
} 

public class FolderModel : NodeModel 
{ 
    // blah 
} 

public class Folder : Node 
{ 
    public virtual NodeModel CreateModel() 
    { 
     var node = new FolderModel(); 
     blah; 
     return node; // FolderModel derives from NodeModel 
    } 
} 

public class ItemModel : NodeModel 
{ 
    // blah 
} 

public class Item : Node 
{ 
    public virtual NodeModel CreateModel() 
    { 
     var node = new ItemModel(); 
     blah; 
     return node; // ItemModel derives from NodeModel 
    } 
} 

public foo(Node node) 
{ 
    var model = node.CreateModel(); 
} 

類型的model取決於類型的節點。 操縱模型的特定部分必須以某種方式成爲知道每個特定模型的內部函數的虛擬節點方法的一部分。

0
public abstract class Node 
{ 
    public virtual NodeModel CreateModel() 
    { 
     throw new NotImplementedException(); 
    } 
} 

public class Folder : Node 
{ 
    public virtual FolderModel CreateModel() 
    { 
     // Implementation 
    } 
} 

這不是重寫方法,而是重載。

Node node=new Folder(); 
node.CreateModel();//Of Folder 

要做到這一點,你必須覆蓋CreateModel在派生(文件夾)類

相關問題