作为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#的限制(没有逆变参数支持)?
答案 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属性?或者我错过了什么?