今天我在做面试题的时候遇到这样一个题目:
程序设计: 猫大叫一声,所有的老鼠都开始逃跑,主人被惊醒。(C#语言)
这道题考的是c#的多态那一部分,这样的题网上很多,我很快从网上查到了答案,答案有两种解法,解法一:这道题目其实是就是三个对象一系列的动作,由猫引发联动效果,类似订阅报纸,这让我们很容易想到观察者模式,通过接口编程的方式实现,这个不多说。解法二:就是多态的舞台了,通过抽象类,委托,事件实现。
废话不多说,我想在这里说的不是解法,而是通过研究第二种解法我进一步加深了对base这个关键字的理解,以及为什么这样这用?在什么场合下咱们得想到她?我在网上查了好多,发现说的不太具体,很难理解!所以我自己用自己的话总结一下,就是希望大家尤其是新手都能真正的理解这个关键字。
首先,看看我找到的这个第二种解法吧!
public delegate void SubEventHander(); public abstract class Subject { public event SubEventHander SubEvent; public void FireAway() { if (SubEvent != null) SubEvent(); } } public abstract class Observer{ public Observer(Subject sub) { sub.SubEvent += new SubEventHander(Response); } public abstract void Response(); } public class mouse:Observer { private string _name; public mouse(string name,Subject sub):base(sub) { this._name = name; } public override void Response() { Console.WriteLine("{0}跑了",this._name); } } public class master : Observer { public master(Subject sub):base(sub){ } public override void Response() { Console.WriteLine("主人惊醒了"); } } public class cat : Subject { public void cry() { Console.WriteLine("猫叫了"); this.FireAway(); } }
咱们直接说和base有关的东西,上述代码有两处用到base,一个是mouse类的构造函数,另外一个是master类的构造函数,先暂时不要管这里为什么要用base,而且base
为什么还带参数。首先,请你看一下这两个类的基类的构造函数,你会发现什么问题?给读者思考的一小段空间。。。。
你会发现基类的构造函数使我们自定义的,我们想让这两个派生类在实例化的时候所调用的基类的构造函数是我们自定义的这个构造函数,说到这里,我顿一下。我又问了,这和自定义的构造函数有关系么?当然有!因为系统在new一个类时,会默认在这个类里创建一个无参的构造函数,如果你后期自定义一个构造函数,这个自动创建的构造函数仍然存在,只不过我们看不到而已,也就说当你自定义一个构造函数,在这个类里会存在两个构造函数,一个是我们自定义的那个,另外一个就是我们看不到的那个无参的构造函数。说到这里,我想说一下,如果大牛们有不同意见,可以评论,大家一同探讨。
我们继续,接下来问题又出现了,既然是两个构造函数,当我们的派生类实例化的时候,我们怎么能够控制系统调用基类的哪个构造函数呢?是那个自定义的无参构造函数?还是我们自定义的那个呢?我们当然知道基类必须调用的是我们自定义的那个构造函数啊!因为我们要注册事件的!
哈哈!现在主角该上场了!base就是我们解决这个问题的武器!只要我们在派生类构造函数后面加上:base(这里是基类构造函数的参数,可以是多个,注意是实例),这样就能根据参数区分开调用那个构造函数了。上述代码中,我们需要调用Observer类的那个带Subject变量参数的构造函数,所以我们要在这两个派生类后面加:base(sub)
最后总结一下:
base关键字在于声明派生类实例化时调用基类的哪一个构造函数,因为如果类不自定义构造参数,
系统默认有一个无参的构造函数,因为base()括号里是构造函数的参数,所以不填调用的是默认的无参构造函数,
有参(可以是多个)调用的是自定义的构造函数,如果自定义构造参数记得使用base关键字指明基类的构造函数
我再强调一下:上面都是我自己的总结,如果有什么不到位的地方,如果大牛们有不同意见,可以评论,大家一同探讨。谢谢支持!