面向对象三大特性之多态

多态是什么?

    用一句话来概括下,多态就是同一操作(方法)作用于不同的对象时,可以有不同的解释,产生不同的执行结果。这句话看似简

    单,实则颇有深意。下面我们来深入理解一多态的意义及如何使用多态。

 

使用多态编程的好处

    在使用继承编程的时候,我们一般是把不同子类的方法分别写在不同的子类中,使用的时候用is a关键字来判断对象是哪种类型

    的,然后进行强制转换来使用不同对象的方法。

      但是,如果有多个子类的话,使用的时候难道要写多个if语句来判断对象是哪种类型的吗?这样会产生很多冗余代码,也会很繁

    琐。

    使用多态编程可以很好的解决这个问题。在父类写一个虚方法或抽象方法,子类去重写父类的方法,在调用的时候系统会根据对

    象运行时的类型决定调用哪个方法。这样子是不是简洁多了?

 

小例子

    假设我们有一个“书”类,然后有很多子类继承“书”类。例如“计算机组成原理”类继承“书类”,“深入Java面向对象”继承“书”类...

    而这些子类都有类似的方法,即被不同的人使用。

    下面我们来用代码实现它。

 1 /// <summary>
 2     /// 演示类
 3     /// </summary>
 4     class Demo
 5     {
 6         List<Book> books = new List<Book>();
 7 
 8         /// <summary>
 9         /// 测试
10         /// </summary>
11         public void Test()
12         {
13             books.Add(new ComputerBook());
14             books.Add(new JavaBook());
15 
16             foreach (Book item in books)
17             {
18                 if (item is ComputerBook)
19                 {
20                     ((ComputerBook)item).ByReading();
21                 }
22                 if (item is JavaBook)
23                 {
24                     ((JavaBook)item).ByReading();
25                 }
26             }
27         }
28     }
29 
30     /// <summary>
31     /// 书类
32     /// </summary>
33     class Book
34     {
35         
36     }
37 
38     /// <summary>
39     /// 计算机书籍
40     /// </summary>
41     class ComputerBook : Book
42     {
43         /// <summary>
44         /// 被阅读
45         /// </summary>
46         public void ByReading()
47         {
48             Console.WriteLine("我是计算机类书籍,被在校大学生使用。");
49         }
50     }
51 
52     /// <summary>
53     /// Java书籍
54     /// </summary>
55     class JavaBook : Book
56     {
57         /// <summary>
58         /// 被阅读
59         /// </summary>
60         public void ByReading()
61         {
62             Console.WriteLine("我是Java书籍,被在业Java程序员使用。");
63         }
64     }

     

 

     通过这段代码可以发现:在使用子类对象的时候需要先用is a来判断子类对象时哪种类型的。那么也就是说,如果一个父类有10

     个派生类(子类)的话,就要用10个if判断语句来判断子类对象是哪种类型了,未免太过繁琐。

     这时,虚方法就该登场了。

 

虚方法

     概念:

        虚方法有方法体,可以被重写,使用virtual来修饰。

        父类中的虚方法并非必须被子类重写,在父类中可以给出虚方法的默认实现。如果子类不重写父类的虚方法则依然执行

        父类的默认实现。如果子类重写了父类的虚方法,则执行子类重写后的方法。

        其实方法重载也是实现多态的一种形式,只是重载的方法都在同一个类中,而用虚方法实现多态的方法散布在有继承关

        系的多个类中。

    使用:

        在父类中使用virtual关键字定义虚方法,在子类中使用override关键字来重写父类中的虚方法。

    override关键字:

        通过override关键字来修饰的方法,称为方法的重写。

 

    下面我们用虚方法来改造一下上面的例子

 1     /// <summary>
 2     /// 演示类
 3     /// </summary>
 4     class Demo
 5     {
 6         List<Book> books = new List<Book>();
 7 
 8         /// <summary>
 9         /// 测试
10         /// </summary>
11         public void Test()
12         {
13             books.Add(new ComputerBook());
14             books.Add(new JavaBook());
15             //遍历时不用加判断
16             foreach (Book item in books)
17             {
18                 item.ByReading();
19             }
20         }
21     }
22 
23     /// <summary>
24     /// 书类
25     /// </summary>
26     class Book
27     {
28         public virtual void ByReading()
29         {
30 
31         }
32     }
33 
34     /// <summary>
35     /// 计算机书籍
36     /// </summary>
37     class ComputerBook : Book
38     {
39         /// <summary>
40         /// 被阅读
41         /// </summary>
42         public override void ByReading()
43         {
44             Console.WriteLine("我是计算机类书籍,被在校大学生使用。");
45         }
46     }
47 
48     /// <summary>
49     /// Java书籍
50     /// </summary>
51     class JavaBook : Book
52     {
53         /// <summary>
54         /// 被阅读
55         /// </summary>
56         public override void ByReading()
57         {
58             Console.WriteLine("我是Java书籍,被在业Java程序员使用。");
59         }
60     }

    

 

    可以看出,使用虚方法来写代码简便了许多。但是问题又来了,一般子类的父类和在父类中的虚方法是“宏观”的,“抽象”的,我

    们不想让这个父类被实例化并且只提供方法的定义,由子类去实现这个方法,该怎么做呢?

    如何解决这个问题呢?我们可以使用抽象类和抽象方法来实现。

 

抽象类和抽象方法

    abstract关键字:

        abstract关键字用来修饰抽象类和抽象方法。

    抽象类:

        使用abstract关键字修饰的抽象类不能被实例化。

        抽象类中可以有非抽象方法。

        抽象类不能是密封的或者静态的。

    抽象方法:

        使用abstract关键字修饰的抽象方法是一个没有实现的方法,由子类重写抽象方法来实现。

        抽象方法没有大括号,直接在小括号后以分号";"结尾。

        含有抽象方法的类必须是抽象类。

        抽象方法必须在其子类中实现,除非它的子类也是抽象类。

    

    下面我们使用抽象类和抽象方法再次改造上面的例子

 1     /// <summary>
 2     /// 演示类
 3     /// </summary>
 4     class Demo
 5     {
 6         List<Book> books = new List<Book>();
 7 
 8         /// <summary>
 9         /// 测试
10         /// </summary>
11         public void Test()
12         {
13             books.Add(new ComputerBook());
14             books.Add(new JavaBook());
15             //遍历时不用加判断
16             foreach (Book item in books)
17             {
18                 item.ByReading();
19             }
20         }
21     }
22 
23     /// <summary>
24     /// 书类
25     /// </summary>
26     abstract class Book
27     {
28         public abstract void ByReading();
29     }
30 
31     /// <summary>
32     /// 计算机书籍
33     /// </summary>
34     class ComputerBook : Book
35     {
36         /// <summary>
37         /// 被阅读
38         /// </summary>
39         public override void ByReading()
40         {
41             Console.WriteLine("我是计算机类书籍,被在校大学生使用。");
42         }
43     }
44 
45     /// <summary>
46     /// Java书籍
47     /// </summary>
48     class JavaBook : Book
49     {
50         /// <summary>
51         /// 被阅读
52         /// </summary>
53         public override void ByReading()
54         {
55             Console.WriteLine("我是Java书籍,被在业Java程序员使用。");
56         }
57     }

     

    

    到了这里,我们可以发现使用虚方法和抽象方法来编程(也就是多态)更符合面向对象编程的思想,并且可以大幅的提升代码的

    可读性和减少冗余的代码。

    用更少的代码实现相同的实现,这感觉,很爽的。

 

 

 

    

 

posted @ 2017-02-23 22:49  南橘  阅读(24927)  评论(3编辑  收藏  举报
蜘蛛