杂七杂八(2)——可以把重写看成是对函数的“重新赋值”
小序:
如此“不严谨”、如此“谬误”的标题,一看就是找骂的!
正文:
前几天在读代码的时候,发现代码里有一些函数,函数体是空的。起初是以为那是为了实现一个Interface或者是一个Abstract类而实际上又没什么实际用处才这么做的,于是没太当回事。今天Anstinus同学指导我写代码的时候,又用到这个“技术”,我才明白——这些函数体为空的函数都被声明为了virtual的,实际上“故意”留给子类去重写的(God~~哪个virtual函数不是“故意”留给子类的)。这个函数体为空的函数,在父类的某个逻辑流程中被调用了,只是因为函数体为空,而什么事都没有做。等到了子类中,一旦子类对这个函数进行了重写,就会个性化地影响到这个逻辑流程。
这种用法之所以特殊,是因为以前我使用virtual函数的时候,注重的是“对原有功能的改写”,这次使用virtual是对一个“根本没有功能”的函数的“功能”进行“改写”。这个感觉像什么呢?呃……以前的改写应该算做“从1到2”,而这次改写应该是“从0到1”。回到我们的标题——如果把函数看成是一个变量,函数的功能(函数体)就是它的值,而重写(override)就好像是对函数进行重新赋值一样,这样,在不同的继承级别上,函数就能获得不同的“值”。
在给出代码之前插一句:无论是变量名、函数名、类名……(简言之就是标识符啦),实际上都是指向一个内存地址,只是变量名指向的内存地址(再加上一个偏移量)里装的是“数值”,数据所占的内存块儿的大小由变量的类型决定;函数名指向的内存地址(再加上一个偏移量)里装的是一组CUP的指令;类名指向的内存地址里装的是这个类(无论是类还是实例)所共用的东西的清单(Table),所以,类实际上是一个作用域(Scope)。
OK,让我们看看今天我遇到的问题的简化版本——感谢Anstinus同学又教会我新东西:)
using System;
namespace Sample
{
class AAA
{
public void DoSomething()
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Do something...");
// Something OPTIONAL
this.DoSomethingOptional(); // 调用了,但在AAA类中,实际上什么事也没做
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Do other things...");
}
protected virtual void DoSomethingOptional() // 函数体是空的
{
}
}
class BBB : AAA
{
protected override void DoSomethingOptional()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("http://blog.csdn.net/FantasiaX");
}
}
class CCC : AAA
{
protected override void DoSomethingOptional()
{
Console.ForegroundColor = ConsoleColor.Magenta;
Console.WriteLine("Some logic in CCC...");
}
}
class Program
{
static void Main(string[] args)
{
AAA aaa = new AAA();
BBB bbb = new BBB();
CCC ccc = new CCC();
aaa.DoSomething();
Console.WriteLine();
bbb.DoSomething();
Console.WriteLine();
ccc.DoSomething();
}
}
}
===============================
这是不是最佳方案?
实际上,几乎任何一个逻辑我们都有不止一种办法来实现它。就拿这个例子而言,完全可以定义一个
delegate void MyDelegate();
并为AAA类声明一个MyDelegate类型的field:
if (optionalThing != null)
{
optionalThing();
}
这样,在子类中,随便你用什么方法,只要把恰当的函数名赋值给optionalThing就可以了。这种方法比起上面代码中的方法要灵活得多、自由得多!
你可能会问:那为什么项目中却没有采用这种方法呢?
原因有如下几个——
- 为了使用这种方法,需要额外定义用途专一的delegate和成员变量,增加了日后维护成本
- 两种方法在代码量上没有太大差别
- 代码中的方法约束力比较强,这样,在子类中的实现看起来会比较一致,实现的时候和日后维护的时候成本较低(实际上,作为下游程序员,我也更喜欢这种方式,copy-paste就能解决很多问题)
所以你看,有时候“缺点”反而是优点!
OK,今天就写到这儿~~做饭去喽!今天是西红柿炒鸡蛋:D
public MyDelegate optionalThing;并把调用“空函数”的地方改写成:
分享到:
相关推荐
java杂七杂八java杂七杂八java杂七杂八java杂七杂八
linux 杂七杂八的资料linux 杂七杂八的资料linux 杂七杂八的资料linux 杂七杂八的资料linux 杂七杂八的资料linux 杂七杂八的资料
杂七杂八的测试资料
各位看官——我就要跟大家乱侃近来入地一个多月,邪门歪地道挖出杂七杂八的东西——的工具——就 汇编。 ——喝口茶先,大家先看看秋镇菜blog上这篇文章《在 Visual C++ 中使用内联汇》 ,详细介绍了在 Visual C++ ...
C++ Builder杂七杂八 都是收藏的编程方面的
模糊控制的一些杂七杂八的资料:模糊控制ch1ch2.ppt模糊控制ch3基本原理.ppt包模糊控制ch4应用实例.ppt包]模糊控制ch5改善系统性能的方法.ppt模糊控制算法c程序.doc模糊算法在智能车控制中的应用.pdf模糊控制算法...
无其他杂七杂八的功能,原生纯净。 服务器演示:http://47.99.218.99:8080/ 账号:admin密码:admin 项目介绍 努力打造一个免费的开源,注释全,文档全适合新手学习,方便快速二次开发的框架。 1.没有基础版,没有...
小学语文近义词杂七杂八的近义词有哪些及造句
杂七杂八攒在一起存着 目录: [apps-for-android-master]() [BmobExample]() [bookmanager]() [FirebaseSample]() [Gson_Fastjson_for_Json]() [highlight]() [Kyhelper]() [mytoolbar]() [Okdroid]() ...
软件开发设计:应用软件开发、系统...云计算与大数据:包括云计算平台、大数据分析、人工智能、机器学习等,云计算是一种基于互联网的计算方式,通过这种方式,共享的软硬件资源和信息可以按需提供给计算机和其他设备。
平时想到的一些杂七杂八的东西 版本 2021-02-19 将大屏展示弄成组件化 2018-11-30 添加了一些东西,也修改了一下里面的文件夹的结构,内容没有变 结构目录 aboutMap 关于地图的一些 BaiduMapTile使用C#写的,可以...
PID的详细调试.pdfPID电机控制.pdfPID调节规律和过程控制.pdf PID过程控制及其参数整定.pdfPID控制算法的C语言实现.PID算法.pdf数字PID及其改进算法.pdf由入门到精通吃透PID.pdf增量式PID.docx
axis2相关jar包, 其中可能有些杂七杂八的jar,无视就可以
js代码-杂七杂八的
NULL 博文链接:https://hao3721.iteye.com/blog/1840208
Miscellaneous 一些杂七杂八的东西
广义表 图元识别 josep排列 jose排列 inver逆序表 paren括号匹配 expr波兰表达式 二叉树(满 前缀 同构 后缀 ) 多机调度 简单路径 非递归遍历 进制方程 嵌套 等价类划分 等等 太多了 不写了 自己下载了看看吧