关于C#间接继承的一些思考:如何修改继承函数的返回值类型


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

当然,本来很简单的一个项目,但是我为了其足够的强大,所以在其中加入了某些复杂概念;且面向概念编程要将这些复杂概念用编码实现;

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

 

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

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

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

 

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

 

如果 如下编码


public class SuperSource<T>{

    public virtual T GetEntity(string key){

        return null;

    }

} 

public class SuperSource: SuperSource<object>{

    public overrideobject GetEntity(stringkey){

        returnnull;

    }

}  

 

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

但是,假如我还有 

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> 这些类如何找到一个公共父类呢?

 

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

 

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

如果: 

public class SuperSource{

     public virtual objectGetEntity(string key){

         returnnull;

     }

}

public class SuperSource<T>: SuperSource{

     public override T GetEntity(string key){  

         returnnull;

     }

}


 

结果很不幸,编译错误:因为可以意会不可言传的某些机制;(我将SuperSource<T> 加上sealed 想避免这个机制,但是编译器依然报错)

 

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

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

SqlConnection  DbConnection IDbConnetion 数据库连接类

我们用    SqlConnection.CreateCommand()       =>     SqlCommand

          DbConnetion.CreateCommand()         =>     DbCommand

          IDbConnection.CreateCommand()       =>     IDbCommand

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

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

 

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

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

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

 

public class SuperSource{

     protected virtual object InnerGetEntity(string key){ returnnull; }

     publc object GetEntity(stringkey){ return InnerGetEntity(key); }

}

 

public class SuperSource<T>: SuperSource{

     protected overridt object InnerGetEntity(string key){ return GetEntity(key);}

     publc new virtual T GetEntity(stringkey){ return null; }

}

 

public class ProdcutSuperSource: SuperSource<Product>{ //酱油类

     publc overridt Product GetEntity(string key){ return new Product(); }

}


 

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)

 

 

 

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

public class TestSource: SuperSource<object>{

     public overridt object GetEntity(string key){ returnnull; }

}


 

我们会发现 TestSource 和 SuperSource  是等价的!

相当于是说 :

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

 

 

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

哎,不写了……

 

 

 

 

 

 

                                                             舒小龙

                                                        2012-01-1010:39


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值