当前位置:
首页 > 编程开发 > Objective-C编程 >
-
c#动静结合编程之泛型委托
制作者:剑锋冷月 单位:无忧统计网,www.51stat.net
多态
多态是什么?一句话:接口和实现的1:n映射。多态让程序能通过统一的接口(广义的接口,意指规范)调用不同的实现,从而增强程序的表达能力和灵活性。我们最为熟悉的多态形式是包括接口继承在内的类型多态:
var animals = new List<IAnimal>() {
new Cat("Missy"),
new Cat("Mr. Bojangles"),
new Dog("Lassie")
};
foreach (var animal in animals) {
Console.WriteLine(animal.Name + ": " + animal.Talk());
}
有时,我们常常混淆继承与多态之间的关系,甚至认为二者是同一概念的不同方面。这里我尝试理清二者之间的区别与联系。在C#中,继承有两方面的功能:1.派生类复用基类的非私有成员和方法;2.实现类型多态。功能1的本质是“复用”,即派生类通过继承复用基类代码,基类与派生类之间处于同一抽象层次;功能2的本质是“被复用”,即派生类通过继承以基类/接口的名义被复用,基类与派生类是抽象与具体的关系。
我们常常把“基类”(base class)随意称作“父类”,不加区别,这在概念上是值得商榷的。“父子关系”是什么?儿子继承父亲的某些特征,强调的是复用,儿子与父亲是同一抽象层次的事物,只体现了继承的复用功能。“动物和狗的关系”显然不同于“父子关系”,动物与狗是抽象与具体的关系,程序中建立这种关系的主要目的在于以抽象的名义被复用,而非复用基类功能。因此,当继承的主要目的是复用时,我们可以把同一抽象层次上的基类称作“父类”,而当继承的主要目的是实现类型多态被复用时,“父类”的提法是欠妥的。
正是由于对继承功能两个方面欠缺清晰的认识,导致所谓的“滥用继承”。前文已经谈到过,继承是很强的类型约束,当目的只是为了复用时,如果采用继承的方式,往往会带来一些副作用,比如:在C#中,对象在其生命周期内无法改变继承关系,儿子像老子就必须像一辈子。其实复用并非OO的专利,在几乎所有场合,我们都可以通过其他方式实现复用,比如组合方式。因此,这里给出一条避免滥用继承的明确建议:当目的是复用,请考虑采用组合,而非继承!
泛型委托
多态与继承没有必然的联系,继承只是实现类型多态的一种手段。我理解,凡是符合接口与实现的1:n映射都属于多态。那么C#中的委托是不是多态呢?当然是,我姑且称它为方法多态,委托的调用者通过统一的委托调用不同的方法实现。与继承多态相比,委托消除了类型约束,凡是符合签名的方法都可以被委托调用,因此更加灵活。还有,泛型是不是多态呢?也是。泛型类/方法的编写者,通过使用统一的类型参数T表达程序的行为,把T具体化的工作交给泛型类/方法的用户。
委托是多态,泛型是多态,那么泛型委托是不是多态呢?当然更是,而其是非常强大的多态!其强大就在于融合了泛型和委托的抽象能力,又不失静态类型的安全性。GoF早就曾意识到泛型与委托相结合将是多么强大的抽象能力啊!而有幸的是,C#早已在语言层面直接支持泛型委托(据我所知,C++ boost库也提供了类似泛型委托的泛型函数指针)。
编缉推荐阅读以下文章
多态
多态是什么?一句话:接口和实现的1:n映射。多态让程序能通过统一的接口(广义的接口,意指规范)调用不同的实现,从而增强程序的表达能力和灵活性。我们最为熟悉的多态形式是包括接口继承在内的类型多态:
var animals = new List<IAnimal>() {
new Cat("Missy"),
new Cat("Mr. Bojangles"),
new Dog("Lassie")
};
foreach (var animal in animals) {
Console.WriteLine(animal.Name + ": " + animal.Talk());
}
有时,我们常常混淆继承与多态之间的关系,甚至认为二者是同一概念的不同方面。这里我尝试理清二者之间的区别与联系。在C#中,继承有两方面的功能:1.派生类复用基类的非私有成员和方法;2.实现类型多态。功能1的本质是“复用”,即派生类通过继承复用基类代码,基类与派生类之间处于同一抽象层次;功能2的本质是“被复用”,即派生类通过继承以基类/接口的名义被复用,基类与派生类是抽象与具体的关系。
我们常常把“基类”(base class)随意称作“父类”,不加区别,这在概念上是值得商榷的。“父子关系”是什么?儿子继承父亲的某些特征,强调的是复用,儿子与父亲是同一抽象层次的事物,只体现了继承的复用功能。“动物和狗的关系”显然不同于“父子关系”,动物与狗是抽象与具体的关系,程序中建立这种关系的主要目的在于以抽象的名义被复用,而非复用基类功能。因此,当继承的主要目的是复用时,我们可以把同一抽象层次上的基类称作“父类”,而当继承的主要目的是实现类型多态被复用时,“父类”的提法是欠妥的。
正是由于对继承功能两个方面欠缺清晰的认识,导致所谓的“滥用继承”。前文已经谈到过,继承是很强的类型约束,当目的只是为了复用时,如果采用继承的方式,往往会带来一些副作用,比如:在C#中,对象在其生命周期内无法改变继承关系,儿子像老子就必须像一辈子。其实复用并非OO的专利,在几乎所有场合,我们都可以通过其他方式实现复用,比如组合方式。因此,这里给出一条避免滥用继承的明确建议:当目的是复用,请考虑采用组合,而非继承!
泛型委托
多态与继承没有必然的联系,继承只是实现类型多态的一种手段。我理解,凡是符合接口与实现的1:n映射都属于多态。那么C#中的委托是不是多态呢?当然是,我姑且称它为方法多态,委托的调用者通过统一的委托调用不同的方法实现。与继承多态相比,委托消除了类型约束,凡是符合签名的方法都可以被委托调用,因此更加灵活。还有,泛型是不是多态呢?也是。泛型类/方法的编写者,通过使用统一的类型参数T表达程序的行为,把T具体化的工作交给泛型类/方法的用户。
委托是多态,泛型是多态,那么泛型委托是不是多态呢?当然更是,而其是非常强大的多态!其强大就在于融合了泛型和委托的抽象能力,又不失静态类型的安全性。GoF早就曾意识到泛型与委托相结合将是多么强大的抽象能力啊!而有幸的是,C#早已在语言层面直接支持泛型委托(据我所知,C++ boost库也提供了类似泛型委托的泛型函数指针)。
编缉推荐阅读以下文章
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
SQL Server -- 解决存储过程传入参数作为s
关于JS定时器的整理
JS中使用Promise.all控制所有的异步请求都完
js中字符串的方法
import-local执行流程与node模块路径解析流程
检测数据类型的四种方法
js中数组的方法,32种方法
前端操作方法
数据类型
window.localStorage.setItem 和 localStorage.setIte
如何完美解决前端数字计算精度丢失与数