abstract:继承和多态*继承可以让class具有一种特殊的能力,即实现class本身定义的所有功能外,还可以对父类(或称为基类、超类)的某些属性和功能进行扩展,这样的类我们称之为子类(或派生类)。继承有如下的几个规则:1. 可传递性:如: C是B的子类,B是A的子类,那么C会同时继承B和A;(object为所有类的基类)2. 唯扩展性:子类应是对父类的扩展,而不能在子类除去父类里面的定义;3. 构造函数和析构
继承和多态
*继承可以让class具有一种特殊的能力,即实现class本身定义的所有功能外,还可以对父类(或称为基类、超类)的某些属性和功能进行扩展,这样的类我们称之为子类(或派生类)。
继承有如下的几个规则:
1. 可传递性:
如: C是B的子类,B是A的子类,那么C会同时继承B和A;(object为所有类的基类)
2. 唯扩展性:
子类应是对父类的扩展,而不能在子类除去父类里面的定义;
3. 构造函数和析构函数不能被继承:
除去构造函数和析构函数不能被继承,其他的成员都能被继承(注意区别:能被继承和能被访问,是两个概念)
4. 重载屏蔽性:
如果子类定义了和父类成员同名的新成员,那么会执行重载和覆盖逻辑。但要明白的是,这样做,并不是删除了父类的这些成员,而是不能再访问这些被重载和覆盖的成员而已。
5. 子类可以从父类的虚方法、虚属性以及虚索引器进行重载(即多态)
我们可以借用override关键字对父类的虚方法、虚属性以及虚索引器进行重载;
同时,我们也可以借用override关键字对抽象父类的抽象方法进行重载。
abstract和virtural的区别:
(1) abstract可以修饰class以及abstract class内部的函数、属性和索引器;而virtual不可以修饰class;
(2) abstract修饰内部的函数、属性和索引器的时候,必须在abstract class才可以;而且abstract函数、属性和索引器不可以在abstract class里面有实现,但virtual必须要有实现。
(3) virtual既可以修饰abstract class里面的函数、属性和索引器,也可以修饰一般class里面的函数、属性和索引器;
*基础知识扩展:什么是索引器?
索引器允许类或者结构的实例按照与数组相同的方式进行索引取值,索引器与属性类似,不同的是索引器的访问是带参的。
A. 索引器和数组比较:
(1)索引器的索引值(Index)类型不受限制;
(2)索引器允许重载;
(3)索引器不是一个变量;
B. 索引器和属性的不同点
(1)属性以名称来标识,索引器以函数形式标识;
(2)索引器可以被重载,属性不可以;
(3)索引器不能声明为static,属性可以;
下面一个简单的例子可见一斑:
public class MyClass { private string[] _strArray; public MyClass(int length) { this._strArray = new string[length]; } public string this[int index] { get { if (index < this._strArray.Length) { return this._strArray[index]; } return null; } set { if (index < this._strArray.Length) { this._strArray[index] = value; } } } }
static void Main(string[] args) { MyClass myClass = new MyClass(3); myClass[0] = "A"; myClass[1] = "B"; myClass[2] = "C"; Console.WriteLine(myClass[0]); Console.WriteLine(myClass[1]); Console.WriteLine(myClass[2]); Console.ReadLine(); }
运行结果:
A
B
C
6. 子类只能继承一个父类(class),而可以继承多个接口(interface)(多重继承)
*多态性:同一操作作用于不同的类的实例,将产生不同的执行结果,即不同类的对象收到相同的消息时,得到不同的结果。
下图所示的类之间继承关系和多态用法,可以让大家更好了解这些概念的意义:
具体的实现代码:
public abstract class Creature { private string _spiece; public Creature(string spiece) { this._spiece = spiece; } public string Spiece { get { return this._spiece; } } public abstract void Breath(); }
public class Animal : Creature { private bool? _sex; public Animal(string spiece) : base(spiece) { this._sex = null; } public bool? Sex { get { return _sex; } } public virtual void Run() { Console.WriteLine("I am running..."); } public override void Breath() { Console.WriteLine("I am breathing by animal respiration..."); } }
public class Monkey : Animal { public Monkey(string spiece) : base(spiece) { } public void ClimbTree() { Console.WriteLine("I am climbing tree..."); } public override void Run() { Console.WriteLine("I am running with two legs, sometimes with four legs..."); } public override void Breath() { Console.WriteLine("I am breathing with lung..."); } }
public class Fish : Animal { public Fish(string spiece) : base(spiece) { } public override void Run() { Console.WriteLine("I am running in the water with fins..."); } public override void Breath() { Console.WriteLine("I am breathing with cheek..."); } }
public class Plant : Creature { public Plant(string spiece) : base(spiece) { } public override void Breath() { Console.WriteLine("I am breathing by plant respiration..."); } }
public class Tree : Plant { public Tree(string spiece) : base(spiece) { } //重载Breath()内部调用base.Breath(),其实和不写没啥区别,这里只是想告诉大家本质是什么。 public override void Breath() { base.Breath(); } }
程序运行测试代码:
class Program { static void Main(string[] args) { Creature creature001 = new Animal("Animal"); Console.WriteLine(creature001.Spiece); creature001.Breath(); Console.WriteLine("—————————————————————————"); Creature creature002 = new Plant("Plant"); Console.WriteLine(creature002.Spiece); creature002.Breath(); Console.WriteLine("—————————————————————————"); Animal animal001 = new Animal("Animal", true); Console.WriteLine(animal001.Spiece); Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", animal001.Spiece, GetSexName(animal001.Sex))); animal001.Breath(); animal001.Run(); Console.WriteLine("—————————————————————————"); Creature monkey001 = new Monkey("Monkey", true); Console.WriteLine(monkey001.Spiece); monkey001.Breath(); Console.WriteLine("—————————————————————————"); Animal animal002 = new Monkey("Monkey", false); Console.WriteLine(animal002.Spiece); Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", animal002.Spiece, GetSexName(animal002.Sex))); animal002.Breath(); animal002.Run(); Console.WriteLine("—————————————————————————"); Creature fish001 = new Fish("Fish", true); Console.WriteLine(fish001.Spiece); monkey001.Breath(); Console.WriteLine("—————————————————————————"); Animal fish002 = new Fish("Fish", true); Console.WriteLine(fish001.Spiece); Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", fish002.Spiece, GetSexName(fish002.Sex))); fish002.Breath(); fish002.Run(); Console.WriteLine("—————————————————————————"); Animal animal004 = new Monkey("Monkey", false); Console.WriteLine(animal004.Spiece); Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", animal004.Spiece, GetSexName(animal004.Sex))); animal002.Breath(); animal002.Run(); Console.WriteLine("—————————————————————————"); Monkey jack = new Monkey("Monkey", true); Console.WriteLine(jack.Spiece); Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", jack.Spiece, GetSexName(jack.Sex))); jack.Breath(); jack.Run(); jack.ClimbTree(); Console.ReadLine(); } private static string GetSexName(bool? value) { string sexName = null; if (value == null) { sexName = "undefined"; } else { sexName = value.Value ? "male" : "female"; } return sexName; } }
运行结果:
Animal I am breathing by animal respiration... ————————————————————————— Plant I am breathing by plant respiration... ————————————————————————— Animal Spiece:Animal; Sex:male I am breathing by animal respiration... I am running... ————————————————————————— Monkey I am breathing with lung... ————————————————————————— Monkey Spiece:Monkey; Sex:female I am breathing with lung... I am running with two legs, sometimes with four legs... ————————————————————————— Fish I am breathing with lung... ————————————————————————— Fish Spiece:Fish; Sex:male I am breathing with cheek... I am running in the water with fins... ————————————————————————— Monkey Spiece:Monkey; Sex:female I am breathing with lung... I am running with two legs, sometimes with four legs... ————————————————————————— Monkey Spiece:Monkey; Sex:male I am breathing with lung... I am running with two legs, sometimes with four legs... I am climbing tree...
*多重继承
类和接口都可以继承接口,而且可以继承不止一个接口。
需求:
IDraw接口,定义DrawLine、DrawCircle和DrawRectangle方法;
Drawer,定义为抽象类,实现IDraw接口,附加属性Name;
ImpressionistDrawer(印象画派画家)类,继承Drawer抽象类;
RealismDrawer(写实主义画派画家)类,继承Drawer抽象类。
如此,代码如下:
public interface IDraw { void DrawLine(); void DrawCircle(); void DrawRectangle(); }
public abstract class Drawer : IDraw { private string _name; public Drawer(string name) { this._name = name; } public string Name { get { return this._name; } } public abstract void DrawLine(); public abstract void DrawCircle(); public abstract void DrawRectangle(); }
//印象画派画家 public class ImpressionistDrawer : Drawer { public ImpressionistDrawer(string name) : base(name) { } public override void DrawLine() { Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a line with pen.", this.Name)); } public override void DrawCircle() { Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a circle with pen.", this.Name)); } public override void DrawRectangle() { Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a rectangle with pen.", this.Name)); } }
//写实主义画派画家 public class RealismDrawer : Drawer { public RealismDrawer(string name) : base(name) { } public override void DrawLine() { Console.WriteLine(string.Format("The realism drawer:{0} is drawing a line with pencil.", this.Name)); } public override void DrawCircle() { Console.WriteLine(string.Format("The realism drawer:{0} is drawing a circle with pencil.", this.Name)); } public override void DrawRectangle() { Console.WriteLine(string.Format("The realism drawer:{0} is drawing a rectangle with pencil.", this.Name)); } }
调用:
static void Main(string[] args) { IDraw draw001 = new RealismDrawer("莫柰"); draw001.DrawCircle(); draw001.DrawLine(); draw001.DrawRectangle(); Console.WriteLine(); IDraw draw002 = new ImpressionistDrawer("弗洛伊德"); draw002.DrawCircle(); draw002.DrawLine(); draw002.DrawRectangle(); Console.ReadLine(); }
运行结果:
The realism drawer:莫柰 is drawing a circle with pencil.
The realism drawer:莫柰 is drawing a line with pencil.
The realism drawer:莫柰 is drawing a rectangle with pencil.
The impressionist drawer:弗洛伊德 is drawing a circle with pen.
The impressionist drawer:弗洛伊德 is drawing a line with pen.
The impressionist drawer:弗洛伊德 is drawing a rectangle with pen.
扩展一下,比方说:这些画家除了要画画之外,一样都要吃饭睡觉打豆豆,怎么处理呢?
我们当然不能把吃饭睡觉打豆豆归为IDraw这个intercace里面,因为这完全是不相干的行为呀!于是,我们考虑新建一个interface
public interface ILive { void EatRice(); void Sleep(); void BeatDouDou(); }
public abstract class Drawer : IDraw, ILive { private string _name; public Drawer(string name) { this._name = name; } #region IDraw public string Name { get { return this._name; } } public abstract void DrawLine(); public abstract void DrawCircle(); public abstract void DrawRectangle(); #endregion #region ILive public abstract void EatRice(); public abstract void Sleep(); public abstract void BeatDouDou(); #endregion }
public ImpressionistDrawer(string name) : base(name) { } public override void DrawLine() { Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a line with pen.", this.Name)); } public override void DrawCircle() { Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a circle with pen.", this.Name)); } public override void DrawRectangle() { Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a rectangle with pen.", this.Name)); } public override void EatRice() { Console.WriteLine(string.Format("The impressionist drawer:{0} is eating rice.", this.Name)); } public override void Sleep() { Console.WriteLine(string.Format("The impressionist drawer:{0} is sleeping.", this.Name)); } public override void BeatDouDou() { Console.WriteLine(string.Format("The impressionist drawer:{0} is beating DouDou.", this.Name)); } }
public class RealismDrawer : Drawer { public RealismDrawer(string name) : base(name) { } public override void DrawLine() { Console.WriteLine(string.Format("The realism drawer:{0} is drawing a line with pencil.", this.Name)); } public override void DrawCircle() { Console.WriteLine(string.Format("The realism drawer:{0} is drawing a circle with pencil.", this.Name)); } public override void DrawRectangle() { Console.WriteLine(string.Format("The realism drawer:{0} is drawing a rectangle with pencil.", this.Name)); } public override void EatRice() { Console.WriteLine(string.Format("The realism drawer:{0} is eating rice.", this.Name)); } public override void Sleep() { Console.WriteLine(string.Format("The realism drawer:{0} is sleeping.", this.Name)); } public override void BeatDouDou() { Console.WriteLine(string.Format("The realism drawer:{0} is beating DouDou.", this.Name)); } }
调用:
static void Main(string[] args) { IDraw drawer001 = new RealismDrawer("莫柰"); drawer001.DrawCircle(); drawer001.DrawLine(); drawer001.DrawRectangle(); Console.WriteLine(); IDraw drawer002 = new ImpressionistDrawer("弗洛伊德"); drawer002.DrawCircle(); drawer002.DrawLine(); drawer002.DrawRectangle(); Console.WriteLine(); ILive drawer003 = new RealismDrawer("莫柰"); drawer003.EatRice(); drawer003.Sleep(); drawer003.BeatDouDou(); Console.WriteLine(); ILive drawer004 = new RealismDrawer("弗洛伊德"); drawer004.EatRice(); drawer004.Sleep(); drawer004.BeatDouDou(); Console.ReadLine(); }
运行结果:
The realism drawer:莫柰 is drawing a circle with pencil. The realism drawer:莫柰 is drawing a line with pencil. The realism drawer:莫柰 is drawing a rectangle with pencil. The impressionist drawer:弗洛伊德 is drawing a circle with pen. The impressionist drawer:弗洛伊德 is drawing a line with pen. The impressionist drawer:弗洛伊德 is drawing a rectangle with pen. The realism drawer:莫柰 is eating rice. The realism drawer:莫柰 is sleeping. The realism drawer:莫柰 is beating DouDou. The realism drawer:弗洛伊德 is eating rice. The realism drawer:弗洛伊德 is sleeping. The realism drawer:弗洛伊德 is beating DouDou.