现在的位置: 首页 > 综合 > 正文

『架构』C#间接继承:如何修改 继承函数的 返回值类型

2013年03月11日 ⁄ 综合 ⁄ 共 2903字 ⁄ 字号 评论关闭

转载请标明:舒小龙 http://www.cnblogs.com/shuxiaolong/articles/20130205_001.html

 

这段时间,除了公司的项目之外;回家之后,自己还要写一个简单的CMS系统。

当然,本来很简单的一个项目,但是我为了其足够的强大,所以在其中加入了某些复杂概念;

且面向概念编程要将这些复杂概念用编码实现;

在项目过程中,就遇到了一个简单的问题:

 

项目中通用数据源 SuperSource是核心的数据源类;

其中有一个函数 object GetEntity(stringkey);

但是,我希望写出一种泛型 SuperSource<T> ,我希望有一个函数 T GetEntity(stringkey)

 

那么,SuperSourceSuperSource<T> 如何定义,如何决定谁做父亲,谁做儿子?

 

如果 如下编码

 1 public class SuperSource<T>{ 
 2     public virtual T GetEntity(string key){ 
 3         return null; 
 4     } 
 5 } 
 6 
 7 public class SuperSource: SuperSource<object>{ 
 8     public overrideobject GetEntity(stringkey){ 
 9         return null; 
10     } 
11 }

 

 

函数就保持了一致性(父类的调用会自动定位到子类),且符合我们上面的要求;

但是,假如我还有

SuperSource<Product> 和 SuperSource<Article> 和 SuperSource<Link>

 

正好,我有一个通用的编辑界面:SuperEdit.aspx

该页面的功能: 绑定任何 一个“超级数据源”,且GetEntity(urlKey) ,且将返回值绑定到界面;

如果 用上面的继承方式,我们会发现:

Product model = SuperSource<Product>.GetEntity(urlKey)
Article model = SuperSource<Article>.GetEntity(urlKey)
Link model = SuperSource<Link>.GetEntity(urlKey)
object model = SuperSource.GetEntity(urlKey)

前面的引用,我们可以用 object 来接收,但是后面 尖括号中赤裸裸的类名,将让SuperEdit.aspx 不具备无敌的扩展性;

 

如何让 SuperEdit.aspx 的代码中不出现任何 ProductArticleLink这些关系到具体实例的 酱油类(因为逻辑而需要,但不因概念而需要的类)呢??

——就是说:SuperSource<T> 这些类如何找到一个公共父类呢?

 

当天晚上没能想出解决办法,于是就睡觉去了;

 

第二天,突然再次想到 SuperSourceSuperSource<T>的继承关系:

如果:

 1 public class SuperSource{ 
 2     public virtual object GetEntity(string key){ 
 3         return null; 
 4     } 
 5 } 
 6 
 7 public class SuperSource<T>: SuperSource{ 
 8     public override T GetEntity(string key){ 
 9         return null; 
10     } 
11 }

 

结果很不幸,编译错误:因为 子类不能修改 父类函数 的 返回值;

 

那么,究竟该怎么做呢??

于是我想到了我们经常使用的一个类:

SqlConnection DbConnection IDbConnetion 数据库连接类

我们用 SqlConnection.CreateCommand() => SqlCommand
DbConnetion.CreateCommand() => DbCommand
IDbConnection.CreateCommand() => IDbCommand

凭什么微软就可以在继承父类的同时,改变父类的函数的类型

——难道就因为C#是他发明的,所以他就有权利避开编译器??

 

经过反编译之后,结果确实不是那样:

微软运用了间接继承(我不知道该怎么定义这个机制,就用“间接继承”吧)机制!

于是我写出了 自己想要的 SuperSource 代码,代码如下:

 

 1 public class SuperSource{ 
 2     protected virtual object InnerGetEntity(string key){ return null; } 
 3     public object GetEntity(stringkey){ return InnerGetEntity(key); } 
 4 } 
 5 
 6 public class SuperSource<T>: SuperSource{ 
 7     protected overridt object InnerGetEntity(string key){ return GetEntity(key);} 
 8     public new virtual T GetEntity(stringkey){ return null; } 
 9 } 
10 
11 public class ProdcutSuperSource: SuperSource<Product>{ //酱油类 
12     public override Product GetEntity(string key){ return new Product(); } 
13 }

 

GetEntity(string key) 之间已经没有了任何继承关系;

父子之间实现继承的是 一个不对外公布的 InnerGetEntity(string key) 函数;

而且,你会惊讶的发现:

GetEntity(string key) 虽然不具备继承关系,

但是父类的引用依然会自动定位到子类 的 GetEntity(string key)

——这就是我所说的 间接继承

 

 

现在回到项目 SuperEdit.aspx

SuperSource 现在是所有 “超级数据源”的父类;

SuperSource 可以等于 SuperSource<Product> 或者 SuperSource<Article> 或者SuperSource<Link>

 

SuperEdit.aspx中就只需要下面一行代码, SuperSource 就不用指定具体的 酱油类 了!

object model = SuperSource.GetEntity(urlKey)

 

 

 

顺便,我们扩展一下上面的代码:

 

1 public class TestSource: SuperSource<object>{ 
2     public overridt object GetEntity(string key){ returnnull; } 
3 }

 

我们会发现 TestSourceSuperSource 是等价的!

相当于是说 :

子类继承了父类,父类的变种继承了子类——真够乱伦的……

 

 

创建除了这样一种功能强大,但是如此乱伦的SuperSource 类,我深感罪孽深重!

哎,不写了……

 

 

                                                                                           舒小龙

                                                                                  2012-01-1010:39

抱歉!评论已关闭.