3. 第一章:C#面向对象编程之继承和多态

第一章:C#面向对象编程

 

第三节:继承和多态

*继承可以让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,属性可以;

    下面一个简单的例子可见一斑:

 1     public class MyClass
 2     {
 3         private string[] _strArray;
 4 
 5         public MyClass(int length)
 6         {
 7             this._strArray = new string[length];
 8         }
 9 
10         public string this[int index]
11         {
12             get
13             {
14                 if (index < this._strArray.Length)
15                 {
16                     return this._strArray[index];
17                 }
18                 return null;
19             }
20             set
21             {
22                 if (index < this._strArray.Length)
23                 {
24                     this._strArray[index] = value;
25                 }
26             }
27         }
28     }
 1         static void Main(string[] args)
 2         {
 3             MyClass myClass = new MyClass(3);
 4             myClass[0] = "A";
 5             myClass[1] = "B";
 6             myClass[2] = "C";
 7 
 8             Console.WriteLine(myClass[0]);
 9             Console.WriteLine(myClass[1]);
10             Console.WriteLine(myClass[2]);
11 
12             Console.ReadLine();
13         }

运行结果:
A
B
C

6. 子类只能继承一个父类(class),而可以继承多个接口(interface)(多重继承)

*多态性:同一操作作用于不同的类的实例,将产生不同的执行结果,即不同类的对象收到相同的消息时,得到不同的结果。

下图所示的类之间继承关系和多态用法,可以让大家更好了解这些概念的意义:

具体的实现代码:

 1     public abstract class Creature
 2     {
 3         private string _spiece;
 4 
 5         public Creature(string spiece)
 6         {
 7             this._spiece = spiece;
 8         }
 9 
10         public string Spiece
11         {
12             get { return this._spiece; }
13         }
14 
15         public abstract void Breath();
16     }
 1     public class Animal : Creature
 2     {
 3         private bool? _sex;
 4 
 5         public Animal(string spiece)
 6             : base(spiece)
 7         {
 8             this._sex = null;
 9         }
10 
11         public bool? Sex
12         {
13             get { return _sex; }
14         }
15 
16         public virtual void Run()
17         {
18             Console.WriteLine("I am running...");
19         }
20 
21         public override void Breath()
22         {
23             Console.WriteLine("I am breathing by animal respiration...");
24         }
25     }
 1     public class Monkey : Animal
 2     {
 3         public Monkey(string spiece)
 4             : base(spiece) { }
 5 
 6         public void ClimbTree()
 7         {
 8             Console.WriteLine("I am climbing tree...");
 9         }
10 
11         public override void Run()
12         {
13             Console.WriteLine("I am running with two legs, sometimes with four legs...");
14         }
15 
16         public override void Breath()
17         {
18             Console.WriteLine("I am breathing with lung...");
19         }
20     }
 1     public class Fish : Animal
 2     {
 3         public Fish(string spiece)
 4             : base(spiece) { }
 5 
 6         public override void Run()
 7         {
 8             Console.WriteLine("I am running in the water with fins...");
 9         }
10 
11         public override void Breath()
12         {
13             Console.WriteLine("I am breathing with cheek...");
14         }
15     }
 1     public class Plant : Creature
 2     {
 3         public Plant(string spiece)
 4             : base(spiece) { }
 5 
 6         public override void Breath()
 7         {
 8             Console.WriteLine("I am breathing by plant respiration...");
 9         }
10     }
 1     public class Tree : Plant
 2     {
 3         public Tree(string spiece)
 4             : base(spiece) { }
 5 
 6         //重载Breath()内部调用base.Breath(),其实和不写没啥区别,这里只是想告诉大家本质是什么。
 7         public override void Breath()
 8         {
 9             base.Breath();
10         }
11     }

程序运行测试代码:

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Creature creature001 = new Animal("Animal");
 6             Console.WriteLine(creature001.Spiece);
 7             creature001.Breath();
 8 
 9             Console.WriteLine("—————————————————————————");
10 
11             Creature creature002 = new Plant("Plant");
12             Console.WriteLine(creature002.Spiece);
13             creature002.Breath();
14 
15             Console.WriteLine("—————————————————————————");
16 
17             Animal animal001 = new Animal("Animal", true);
18             Console.WriteLine(animal001.Spiece);
19             Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", animal001.Spiece, GetSexName(animal001.Sex)));
20             animal001.Breath();
21             animal001.Run();
22 
23             Console.WriteLine("—————————————————————————");
24 
25             Creature monkey001 = new Monkey("Monkey", true);
26             Console.WriteLine(monkey001.Spiece);
27             monkey001.Breath();
28 
29             Console.WriteLine("—————————————————————————");
30 
31             Animal animal002 = new Monkey("Monkey", false);
32             Console.WriteLine(animal002.Spiece);
33             Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", animal002.Spiece, GetSexName(animal002.Sex)));
34             animal002.Breath();
35             animal002.Run();
36 
37             Console.WriteLine("—————————————————————————");
38 
39             Creature fish001 = new Fish("Fish", true);
40             Console.WriteLine(fish001.Spiece);
41             monkey001.Breath();
42 
43             Console.WriteLine("—————————————————————————");
44 
45             Animal fish002 = new Fish("Fish", true);
46             Console.WriteLine(fish001.Spiece);
47             Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", fish002.Spiece, GetSexName(fish002.Sex)));
48             fish002.Breath();
49             fish002.Run();
50 
51             Console.WriteLine("—————————————————————————");
52 
53             Animal animal004 = new Monkey("Monkey", false);
54             Console.WriteLine(animal004.Spiece);
55             Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", animal004.Spiece, GetSexName(animal004.Sex)));
56             animal002.Breath();
57             animal002.Run();
58 
59             Console.WriteLine("—————————————————————————");
60 
61             Monkey jack = new Monkey("Monkey", true);
62             Console.WriteLine(jack.Spiece);
63             Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", jack.Spiece, GetSexName(jack.Sex)));
64             jack.Breath();
65             jack.Run();
66             jack.ClimbTree();
67 
68             Console.ReadLine();
69         }
70 
71         private static string GetSexName(bool? value)
72         {
73             string sexName = null;
74             if (value == null)
75             {
76                 sexName = "undefined";
77             }
78             else
79             {
80                 sexName = value.Value ? "male" : "female";
81             }
82             return sexName;
83         }
84     }

运行结果:

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抽象类。

如此,代码如下:

1     public interface IDraw
2     {
3         void DrawLine();
4 
5         void DrawCircle();
6 
7         void DrawRectangle();
8     }
 1     public abstract class Drawer : IDraw
 2     {
 3         private string _name;
 4 
 5         public Drawer(string name)
 6         {
 7             this._name = name;
 8         }
 9 
10         public string Name
11         {
12             get
13             {
14                 return this._name;
15             }
16         }
17 
18         public abstract void DrawLine();
19 
20         public abstract void DrawCircle();
21 
22         public abstract void DrawRectangle();
23     }
 1     //印象画派画家
 2     public class ImpressionistDrawer : Drawer
 3     {
 4         public ImpressionistDrawer(string name)
 5             : base(name) { }
 6 
 7         public override void DrawLine()
 8         {
 9             Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a line with pen.", this.Name));
10         }
11 
12         public override void DrawCircle()
13         {
14             Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a circle with pen.", this.Name));
15         }
16 
17         public override void DrawRectangle()
18         {
19             Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a rectangle with pen.", this.Name));
20         }
21     }
 1     //写实主义画派画家
 2     public class RealismDrawer : Drawer
 3     {
 4         public RealismDrawer(string name)
 5             : base(name) { }
 6 
 7         public override void DrawLine()
 8         {
 9             Console.WriteLine(string.Format("The realism drawer:{0} is drawing a line with pencil.", this.Name));
10         }
11 
12         public override void DrawCircle()
13         {
14             Console.WriteLine(string.Format("The realism drawer:{0} is drawing a circle with pencil.", this.Name));
15         }
16 
17         public override void DrawRectangle()
18         {
19             Console.WriteLine(string.Format("The realism drawer:{0} is drawing a rectangle with pencil.", this.Name));
20         }
21     }

调用:

 1         static void Main(string[] args)
 2         {
 3             IDraw draw001 = new RealismDrawer("莫柰");
 4             draw001.DrawCircle();
 5             draw001.DrawLine();
 6             draw001.DrawRectangle();
 7 
 8             Console.WriteLine();
 9 
10             IDraw draw002 = new ImpressionistDrawer("弗洛伊德");
11             draw002.DrawCircle();
12             draw002.DrawLine();
13             draw002.DrawRectangle();
14 
15             Console.ReadLine();
16         }

运行结果:

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

1     public interface ILive
2     {
3         void EatRice();
4 
5         void Sleep();
6 
7         void BeatDouDou();
8     }
 1     public abstract class Drawer : IDraw, ILive
 2     {
 3         private string _name;
 4 
 5         public Drawer(string name)
 6         {
 7             this._name = name;
 8         }
 9 
10         #region IDraw
11         public string Name
12         {
13             get
14             {
15                 return this._name;
16             }
17         }
18 
19         public abstract void DrawLine();
20 
21         public abstract void DrawCircle();
22 
23         public abstract void DrawRectangle();
24 
25         #endregion
26 
27         #region ILive
28 
29         public abstract void EatRice();
30 
31         public abstract void Sleep();
32 
33         public abstract void BeatDouDou();
34 
35         #endregion
36     }
 1         public ImpressionistDrawer(string name)
 2             : base(name) { }
 3 
 4         public override void DrawLine()
 5         {
 6             Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a line with pen.", this.Name));
 7         }
 8 
 9         public override void DrawCircle()
10         {
11             Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a circle with pen.", this.Name));
12         }
13 
14         public override void DrawRectangle()
15         {
16             Console.WriteLine(string.Format("The impressionist drawer:{0} is drawing a rectangle with pen.", this.Name));
17         }
18 
19         public override void EatRice()
20         {
21             Console.WriteLine(string.Format("The impressionist drawer:{0} is eating rice.", this.Name));
22         }
23 
24         public override void Sleep()
25         {
26             Console.WriteLine(string.Format("The impressionist drawer:{0} is sleeping.", this.Name));
27         }
28 
29         public override void BeatDouDou()
30         {
31             Console.WriteLine(string.Format("The impressionist drawer:{0} is beating DouDou.", this.Name));
32         }
33     }
 1     public class RealismDrawer : Drawer
 2     {
 3         public RealismDrawer(string name)
 4             : base(name) { }
 5 
 6         public override void DrawLine()
 7         {
 8             Console.WriteLine(string.Format("The realism drawer:{0} is drawing a line with pencil.", this.Name));
 9         }
10 
11         public override void DrawCircle()
12         {
13             Console.WriteLine(string.Format("The realism drawer:{0} is drawing a circle with pencil.", this.Name));
14         }
15 
16         public override void DrawRectangle()
17         {
18             Console.WriteLine(string.Format("The realism drawer:{0} is drawing a rectangle with pencil.", this.Name));
19         }
20 
21         public override void EatRice()
22         {
23             Console.WriteLine(string.Format("The realism drawer:{0} is eating rice.", this.Name));
24         }
25 
26         public override void Sleep()
27         {
28             Console.WriteLine(string.Format("The realism drawer:{0} is sleeping.", this.Name));
29         }
30 
31         public override void BeatDouDou()
32         {
33             Console.WriteLine(string.Format("The realism drawer:{0} is beating DouDou.", this.Name));
34         }
35     }

调用:

 1         static void Main(string[] args)
 2         {
 3             IDraw drawer001 = new RealismDrawer("莫柰");
 4             drawer001.DrawCircle();
 5             drawer001.DrawLine();
 6             drawer001.DrawRectangle();
 7 
 8             Console.WriteLine();
 9 
10             IDraw drawer002 = new ImpressionistDrawer("弗洛伊德");
11             drawer002.DrawCircle();
12             drawer002.DrawLine();
13             drawer002.DrawRectangle();
14 
15             Console.WriteLine();
16 
17             ILive drawer003 = new RealismDrawer("莫柰");
18             drawer003.EatRice();
19             drawer003.Sleep();
20             drawer003.BeatDouDou();
21 
22             Console.WriteLine();
23 
24             ILive drawer004 = new RealismDrawer("弗洛伊德");
25             drawer004.EatRice();
26             drawer004.Sleep();
27             drawer004.BeatDouDou();
28 
29             Console.ReadLine();
30         }

运行结果:

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.

posted @ 2016-01-02 01:00  我喂自己袋盐_1989  阅读(251)  评论(0编辑  收藏  举报