在C#中实现接口时如何传递子类参数?

时间:2009-07-15 16:16:27

标签: c# class interface parameters

作为OOP的新手,我试图通过传递(必需的)子类参数来实现带有基本参数的接口方法。我有:


public interface IArticleDataAccess { int SaveArticle(NewsArticle thisArticle); }

public AnalysisDataAccess : IArticleDataAccess {
  public int SaveArticle(AnalysisArticle thisArticle) {
    // Specific save code that needs properties of AnalysisArticle not found in NewsArticle.
}
public class AnalysisArticle : NewsArticle {
  IArticleDataAccess dataAccess = new ArchivedArticleDataAccess();
  int Save() {
    return dataAccess.SaveArticle(this);
  }
}

错误是“ArchivedArticleDataAccess”没有实现接口成员'IArticleDataAccess.SaveArticle(NewsArticle)'“,因为参数类型不一样。

我犯了一个小错误或错过了一个有趣的OOP概念吗?有没有我可以用来做这个的模式?铸造还是仿制药?或者这是C#的限制(没有逆变参数支持)?

5 个答案:

答案 0 :(得分:8)

你不能在这里申请逆转,因为它会破坏合约。我可以通过界面将任何类型的NewsArticle发送到SaveArticle类,然后您的AnalysisDataAccess会禁止...

你应该做的是使用泛型,如下:

public interface IArticleDataAccess<T> where T : NewsArticle
{
    int SaveArticle(T thisArticle);
}

public AnalysisDataAccess : IArticleDataAccess<AnalysisArticle> {
  public int SaveArticle(AnalysisArticle thisArticle) {
    // Specific save code that needs properties of AnalysisArticle not found in NewsArticle.
}
public class AnalysisArticle : NewsArticle {
  IArticleDataAccess<AnalysisArticle> dataAccess = new AnalysisArticleDataAccess();
  int Save() {
    return dataAccess.SaveArticle(this);
  }
}

答案 1 :(得分:2)

你可以这样做。显式实现接口,确保参数是正确的类型,并调用处理实际需要的类型的公共方法。如果NewArticle传递的不是AnalysisArticle,请确保您知道自己想要做什么。此外,请仔细考虑此设计并确定您需要并将AnalysisDataAccess用作IArticleDataAccess。

IArticleDataAccess int SaveArticle(NewsArticle article)
{
    AnalysisArticle analysisArticle = article as AnalysisArticle;
    if (analysisArticle != null)
            SaveArticle(analysisArticle);
    //else handle error or another routine
}

public int SaveArticle(AnalysisArticle thisArticle)
{
     //freely user analysis article members
}

答案 2 :(得分:0)

您收到编译时错误,因为ArchivedArticleDataAccess必须实现IArticleDataAccess,并且其声明需要如下所示:

public class ArchivedArticleDataAccess : IArticleDataAccess 
{
    public int SaveArticle(NewsArticle thisArticle) 
    {
        // Save the article and return some integer
    }
}

而不是:

public class ArchivedArticleDataAccess : IArticleDataAccess 
{
    public int SaveArticle(AnalysisArticle thisArticle) 
    {
        // Save the article and return some integer
    }
}

答案 3 :(得分:0)

您无法更改在接口上实现的方法的类型,您需要更改它,以便在方法实现中将参数转换为正确的类型,如下所示:

public AnalysisDataAccess : IArticleDataAccess {
  public int SaveArticle(NewsArticle thisArticle) {
    AnalysisArticle theArticle = thisArticle as AnalysisArticle;
    if (theArticle != null) {
    // Specific save code that needs properties of AnalysisArticle not found in 

NewsArticle。         }     }

这应该有用。

答案 4 :(得分:0)

仿制药的使用看起来很优雅。但在尝试实现它时,我实际上并没有使用:


IArticleDataAccess<AnalysisArticle> dataAccess = new AnalysisArticleDataAccess();
//But instead have a DataAccess property in NewsArticle.  Once defined as:
IArticleDataAccess DataAccess { get; set; }
//If I change to:
IArticleDataAccess<NewsArticle> DataAccess { get; set; }
// It can't be implicitly set to type IArticleDataAccess<AnalysisArticle>.

我是否还需要通用于NewsArticle&lt; T&gt;?自引用泛型看起来很可怕,需要进行大量更改。最好让每个子类重新实现具有正确类型的DataAccess属性?或者我错过了什么?