zoukankan      html  css  js  c++  java
  • C# 多态理解

     封装、继承、多态,面向对象的三大特性,前两项理解相对容易,但要理解多态,特别是深入的了解,对于初学者而言可能就会有一定困难了。我一直认为学习OO的最好方法就是结合实践,封装、继承在实际工作中的应用随处可见,但多态呢?也许未必,可能不经意间用到也不会把它跟“多态”这个词对应起来。在此抛砖引玉,大家讨论,个人能力有限,不足之处还请指正。
       

        之前看到过类似的问题:如果面试时主考官要求你用一句话来描述多态,尽可能的精炼,你会怎么回答?当然答案有很多,每个人的理解和表达不尽相同,但我比较趋向这样描述:通过继承实现的不同对象调用相同的方法,表现出不同的行为,称之为多态。

    例1:

     
    代码
    public class Animal
        {
            public virtual void Eat()
            {
                Console.WriteLine("Animal eat");
            }
        }

        public class Cat : Animal
        {
            public override void Eat()
            {
                Console.WriteLine("Cat eat");
            }
        }

        public class Dog : Animal
        {
            public override void Eat()
            {
                Console.WriteLine("Dog eat");
            }
        }

        class Tester
        {
            static void Main(string[] args)
            {
                Animal[] animals = new Animal[3];

                animals[0] = new Animal();
                animals[1] = new Cat();
                animals[2] = new Dog();

                for (int i = 0; i < 3; i++)
                {
                    animals[i].Eat();
                }
            }
        }

     

         输出如下:

    Animal eat...

    Cat eat...

    Dog eat...

    在上面的例子中,通过继承,使得Animal对象数组中的不同的对象,在调用Eat()方法时,表现出了不同的行为。

    多态的实现看起来很简单,要完全理解及灵活的运用c#的多态机制,也不是一件容易的事,有很多需要注意的地方。

    1. new的用法

    先看下面的例子。

    例2

     
    代码
    public class Animal
        {
            public virtual void Eat()
            {
                Console.WriteLine("Animal eat");
            }
        }

        public class Cat : Animal
        {
            public new void Eat()
            {
                Console.WriteLine("Cat eat");
            }
        }

        class Tester
        {
            static void Main(string[] args)
            {
                Animal a = new Animal();
                a.Eat();

                Animal ac = new Cat();
                ac.Eat();

                Cat c = new Cat();
                c.Eat();
            }
        }

     

    运行结果为:

    Animal eat...

    Animal eat...

    Cat eat...

    可以看出,当派生类Cat的Eat()方法使用new修饰时,Cat的对象转换为Animal对象后,调用的是Animal类中的Eat()方法。其实可以理解为,使用new关键字后,使得Cat中的Eat()方法和Animal中的Eat()方法成为毫不相关的两个方法,只是它们的名字碰巧相同而已。所以, Animal类中的Eat()方法不管用还是不用virtual修饰,也不管访问权限如何,或者是没有,都不会对Cat的Eat()方法产生什么影响(只是因为使用了new关键字,如果Cat类没用从Animal类继承Eat()方法,编译器会输出警告)。

    我想这是设计者有意这么设计的,因为有时候我们就是要达到这种效果。严格的说,不能说通过使用new来实现多态,只能说在某些特定的时候碰巧实现了多态的效果。

    2.override实现多态

    真正的多态使用override来实现的。回过去看前面的例1,在基类Animal中将方法Eat()用virtual标记为虚拟方法,再在派生类Cat和Dog中用override对Eat()修饰,进行重写,很简单就实现了多态。需要注意的是,要对一个类中一个方法用override修饰,该类必须从父类中继承了一个对应的用virtual修饰的虚拟方法,否则编译器将报错。

    好像讲得差不多了,还有一个问题,不知道你想没有。就是多层继承中又是怎样实现多态的。比如类A是基类,有一个虚拟方法method()(virtual修饰),类B继承自类A,并对method()进行重写(override修饰),现在类C又继承自类B,是不是可以继续对method()进行重写,并实现多态呢?看下面的例子。

    例3:

     
    代码
    public class Animal
        {
            public virtual void Eat()
            {
                Console.WriteLine("Animal eat");
            }
        }

        public class Dog : Animal
        {
            public override void Eat()
            {
                Console.WriteLine("Dog eat");
            }
        }

        public class WolfDog : Dog
        {
            public override void Eat()
            {
                Console.WriteLine("WolfDog eat");
            }
        }

        class Tester
        {
            static void Main(string[] args)
            {
                Animal[] animals = new Animal[3];

                animals[0] = new Animal();
                animals[1] = new Dog();
                animals[2] = new WolfDog();

                for (int i = 0; i < 3; i++)
                {
                    animals[i].Eat();
                }
            }
    }
     

         运行结果为:

    Animal eat...

    Dog eat...

    WolfDog eat... 

    在上面的例子中类Dog继承自类Animal,对方法Eat()进行了重写,类WolfDog又继承自Dog,再一次对Eat()方法进行了重写,并很好地实现了多态。不管继承了多少层,都可以在子类中对父类中已经重写的方法继续进行重写,即如果父类方法用override修饰,如果子类继承了该方法,也可以用override修饰,多层继承中的多态就是这样实现的。要想终止这种重写,只需重写方法时用sealed关键字进行修饰即可。

    3. abstract-override实现多态

    先在我们在来讨论一下用abstract修饰的抽象方法。抽象方法只是对方法进行了定义,而没有实现,如果一个类包含了抽象方法,那么该类也必须用abstract声明为抽象类,一个抽象类是不能被实例化的。对于类中的抽象方法,可以再其派生类中用override进行重写,如果不重写,其派生类也要被声明为抽象类。看下面的例子。

    例4

     
    代码
        public abstract class Animal
        {
          public abstract void Eat();
        }

        public class Cat : Animal
        {
            public override void Eat()
            {
                Console.WriteLine("Cat eat");
            }
        }

        public class Dog : Animal
        {
            public override void Eat()
            {
                Console.WriteLine("Dog eat");
            }
        }

        public class WolfDog : Dog
        {
            public override void Eat()
            {
                Console.WriteLine("Wolfdog eat");
            }
        }

        class Tester
        {
            static void Main(string[] args)
            {
                Animal[] animals = new Animal[3];

                animals[0] = new Cat();
                animals[1] = new Dog();
                animals[2] = new WolfDog();

                for (int i = 0; i < animals.Length; i++)
                {
                    animals[i].Eat();
                }
            }
        }
     

    运行结果为:

    Cat eat...

    Dog eat...

    Wolfdog eat...

    从上面可以看出,通过使用abstract-override可以和virtual-override一样地实现多态,包括多层继承也是一样的。不同之处在于,包含虚拟方法的类可以被实例化,而包含抽象方法的类不能被实例化。

    以上就是我对c#中多态的一些浅薄的认识,如有错误的地方,欢迎批评指正!

  • 相关阅读:
    ERROR Function not available to this responsibility.Change responsibilities or contact your System Administrator.
    After Upgrade To Release 12.1.3 Users Receive "Function Not Available To This Responsibility" Error While Selecting Sub Menus Under Diagnostics (Doc ID 1200743.1)
    产品设计中先熟练使用铅笔 不要依赖Axure
    12.1.2: How to Modify and Enable The Configurable Home Page Delivered Via 12.1.2 (Doc ID 1061482.1)
    Reverting back to the R12.1.1 and R12.1.3 Homepage Layout
    常见Linux版本
    网口扫盲二:Mac与Phy组成原理的简单分析
    VMware 8安装苹果操作系统Mac OS X 10.7 Lion正式版
    VMware8安装MacOS 10.8
    回顾苹果操作系统Mac OS的发展历史
  • 原文地址:https://www.cnblogs.com/newsouls/p/3160232.html
Copyright © 2011-2022 走看看