摘要:继承和多态*继承可以让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.