返回C#面向对象编......登陆

C#面向对象编程之继承和多态

阿神2016-11-12 09:49:24736

继承和多态

*继承可以让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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

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;

                }

            }

        }

    }

1

2

3

4

5

6

7

8

9

10

11

12

13

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)(多重继承)

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

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

854917-20160102032743557-957294752.png

具体的实现代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

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();

    }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

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...");

        }

    }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

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...");

        }

    }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

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...");

        }

    }

1

2

3

4

5

6

7

8

9

10

public class Plant : Creature

    {

        public Plant(string spiece)

            : base(spiece) { }

 

        public override void Breath()

        {

            Console.WriteLine("I am breathing by plant respiration...");

        }

    }

1

2

3

4

5

6

7

8

9

10

11

public class Tree : Plant

    {

        public Tree(string spiece)

            : base(spiece) { }

 

        //重载Breath()内部调用base.Breath(),其实和不写没啥区别,这里只是想告诉大家本质是什么。

        public override void Breath()

        {

            base.Breath();

        }

    }

程序运行测试代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

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;

        }

    }

运行结果:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

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

2

3

4

5

6

7

8

public interface IDraw

    {

        void DrawLine();

 

        void DrawCircle();

 

        void DrawRectangle();

    }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

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();

    }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

//印象画派画家

    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));

        }

    }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

//写实主义画派画家

    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));

        }

    }

调用:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

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

1

2

3

4

5

6

7

8

public interface ILive

    {

        void EatRice();

 

        void Sleep();

 

        void BeatDouDou();

    }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

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

    }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

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));

        }

    }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

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));

        }

    }

调用:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

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();

        }

运行结果:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

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.


最新手记推荐

• 用composer安装thinkphp框架的步骤• 省市区接口说明• 用thinkphp,后台新增栏目• 管理员添加编辑删除• 管理员添加编辑删除

全部回复(0)我要回复

暂无评论~
  • 取消回复发送