【C#】OOP之多态那点事

2018-06-17 19:54:20来源:未知 阅读 ()

新老客户大回馈,云服务器低至5折

前言: 对菜鸟开发者的忠告:花一万个小时练习 Coding,不要浪费一万小时无谓地 Debugging(也就说看代码)

 

                       

看上面的UML图,我们创建一个抽象的Instrument类,类中有一个抽象方法paly,然后所有的子类都继承这个类并实现paly方法。(若不懂继承,请参照另一篇:OOP之继承那点事)

我们来看一下类的实现:

    public abstract class Instrument
    {
        public abstract void Play();
    }

    public class Guitor : Instrument
    {
        public override void Play()
        {
            Console.WriteLine(string.Format("Play {0}", this.GetType().Name));
        }
    }

    public class Paino : Instrument
    {
        public override void Play()
        {
            Console.WriteLine(string.Format("Play {0}", this.GetType().Name));
        }
    }

    public class Violin : Instrument
    {
        public override void Play()
        {
            Console.WriteLine(string.Format("Play {0}", this.GetType().Name));
        }
    }
View Code

在每个子类方法里,我们直接出去字符串。

  class Program
    {
        static void Main(string[] args)
        {
            Guitor g = new Guitor();
            g.Play();

            Paino p = new Paino();
            p.Play();

            Violin v = new Violin();
            v.Play();

            Console.ReadLine();
        }
    }
View Code

在Main方法里,我们创建了三个对象,然后分别输出。 这个说在我们还没开始多态之前的写法,好麻烦有木有(木有?蹲角落写100个乐器的paly).那什么是多态呢?

什么是多态:一种形态的多种表现形式(好抽象...)

THINK IN JAVA上写到:多态是消除类型之间的耦合关系(还是很抽象)

  直接看例子:

    class Program
    {
        static void Main(string[] args)
        {
            PlayInstrument(new Guitor());
            PlayInstrument(new Paino());
            PlayInstrument(new Violin());

            Console.ReadLine();
        }

        public static void PlayInstrument(Instrument instrument)
        {
            instrument.Play();
        }
    }
View Code

  这样的输出是和上面的例子是一样的,我们改变了什么,我们提供了一个方法,把3个子类的引用放了进去,呀,为什么PlayInstrument的形参是Instrument的对象,这就是多态的关键之处,

我总结了一句话:子类的引用(new Guitor())指向父类的对象(Instrument instrument) ;

  

       static void Main(string[] args)
        {
            Instrument instrument = new Guitor();
            instrument = new Paino();
            instrument = new Violin();

            Console.ReadLine();
        }
View Code

   这个好神奇有木有,我初学时间也觉得,这个好神奇,这个这么玩的,让我来带领大家进入神秘的多态空间。

  

  

  向上转型

     

       static void Main(string[] args)
        {
            Guitor gutior = new Guitor();
            Instrument instrument = gutior;


            Console.ReadLine();
        }
View Code

 

向上转型,就说把子类的类型转成父类的,这样是安全的,看上面的例子,如果在VS IDE工具中查看,是没有编译报错的,这时为什么呢?我们来看张图。

这个圆我们把他当作堆(heap)来看,(这没有画栈,因为指向讨论向上转型的安全).我们来看一下Guitor里面包含了Instrument的所有的东西(除了构造,如果说你点不出来私有化的东西,你可以尝试用反射,它的确存在) ,这样我们把大块变成小块是不是很安全呢,因为我大块拥有小块里面所有的东西,所以说向上转型是安全的。

  

注:相反来说,向下转型是危险的,因为小块变成大块,你不可以控制里面的东西。(协变和逆变概念也差不多,我比较喜欢叫成和谐的变->安全,逆天的变->危险)

这样的话,我们把大块转换成小块(Instrument instrument=new Guitor()),我们只能调用到小块的东西了(所以我们在设计的时候,一般会用接口去限定)

  

  接口其实是应该单独拉出来谈的,但是由于接口基本概念不多,只是在我们OO设计中,接口用处很大,这里属于设计范围,在多态中,用接口做父类和用类写法一样的,可以去试试。

  

  总结一下:

  1.向上转型以后,虽然引用还是原本的子类,但是只能用父类的方法了(想想大块变小块)

  2.父类方法被子类重写了(virtual,override)以后,向上转型以后,调用相同的方法还是大块的(因为小块的被重写了,这样说感觉很牵强,因为如果我们在子类中用base关键字还是能调用父类的同名方法,至于这块的内存的调用,我一直没找到相关资料,如果有人知道,请分享一下,万分感谢)。

  3.接口和抽象类(类)在使用多态的上面是同一个形式

  

 

  感觉这边写的不好...望大家补充和指出不足,谢谢了。

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:实现把dgv里的数据完整的复制到一张内存表

下一篇:C#实现对Word文件读写[转]