关于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)

Linkmodel = 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 DbConnectionIDbConnetion数据库连接类

我们用 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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值