zoukankan      html  css  js  c++  java
  • 继承多态绕点 C#篇

    最近在看博客的时候看到一块很绕的地方,有点类似于以前学习C语言是的i++,++i组合到一起使用的情况,很坑b的,绝对会比i++,++i这种情况更有用,虽然实际代码里面确实很少出现.

    面对象像三大特点不是封装,继承和多态吗,绕的地方主要是继承和多态融合到一起的时候.不啰嗦,先看下面代码

        public class Shape { }
        public class Rectangle : Shape { }
        public class Triangle : Shape { }
    
        public class Father
        {
            public void Foo(Rectangle r)
            {
                Console.WriteLine("Father Foo(Rectangle)");
            }
            public virtual void Foo(Triangle t)
            {
                Console.WriteLine("Father Foo(Triangle)");
            }
        }
    
        public class Son : Father
        {
            public void Foo(Shape s)
            {
                Console.WriteLine("Son Foo(Shape)");
            }
            public override void Foo(Triangle t)
            {
                Console.WriteLine("Son override Foo(Triangle)");
            }
        }

    上面三个类是 矩形,三角形 继承 形状,下面两个类是 父亲 有两个方法,一个参数Rectangle的,一个参数Triangle的(这个是虚的),儿子类,一个Shape的方法,一个Triangle的重写方法,这里没有添加一个Rectangle的方法,因为添加了就会覆盖父新的方法.
    理论上现在父亲的对象有两个方法,儿子的对象有三个方法,因为有一个Rectangle的方法继承至父亲.那么看下下面代码输出情况

            Shape s = new Shape();
                Rectangle r = new Rectangle();
                Triangle t = new Triangle();
    
                Father fa = new Son();
                Son so = new Son();
    
                fa.Foo(r);//1
                fa.Foo(t);
    
                so.Foo(s);//2
                so.Foo(r);
                so.Foo(t);

    我们先猜一下//1,//2部分出输什么结果,然后再看一下运行的结果

    //1
    Father Foo(Rectangle)
    Son override Foo(Triangle)
    //2
    Son Foo(Shape)
    Son Foo(Shape)
    Son Foo(Shape)

    我们来看一下是否有绕的地方,//1
    第1行 fa调Rectangle的方法,那到底应该调用子类的Foo(Shape)还是应该从父类继承的Foo(Rectangle)方法,这里一点绕点,程序运行结果是调的继承的Foo(Rectangle)方法
    第2行 fa调Triangle的方法,子类从写了你类的Triangle的方法,标准的多态

    //2 这个为什么都是调子类Foo(Shape) 另一个绕点,为什么这次不调从父类继承的Foo(Rectangle)方法,与上面第一条完全矛盾了啊.

    先我们来分清一下这几个情况里的多态和继承关系,多态发生的条件是 重写,继承,要有父类引用指向子类,
    那么第一组的第1方法调用没有重写,也不是虚方法,所以不是多态,第2个方法调用是多态
    第二组的3个方法调用都不是多态.那没有多态的情况下也应该调我继承的方法啊.

    所以这里总结下在这种情况下有一个调用的先后顺序
    1.有多态的情况下,肯定是在多态系方法里面去调用,哪些是多态系方法呢? 父类的vitual,子类的override就是多态系方法
    2.没有多态的情况下调用自己本生(引用类型,不是this指针)的方法(有的情况下),如果没有再调多态系的方法,自己的方法就是我们的普通方法,new覆盖了的方法,和继承来的方法
    3.在 自身方法,与继承方法又有个先后顺序,先自身(或new,new也就是自身覆盖),后继承方法.就算你在写代码是 点出来的方法里有继承的,但是自己方法也会先调用

    现在再回来看刚才的几个调用绕点的地方
    第一组第1个方法调用,因为不是多态,所以看引用本身,有一个Foo(Rectangle)的方法,所以调父类的(就是他本身的)
    第二组第2个方法调用,不是多态,先看引用类型(声明时,不是运行时)本身,Son的Foo(Shape s)方法可以调用,所以不会调用继承来的Foo(Rectangle)
    第二组第3个方法调用,不是多态,先看引用类型(声时时,不是运行时)本身,Son的Foo(Shape s)可以调用,所以不会考虑继承(这里没有),也不会考虑多态系里的方法(这里有一个)

    对以上的理论纯属个人总结,还没有什么依据,只是大家可以共同多写些例子来测试一下,这个可能同语言解释器有关系,因为Java与C++这一点同C#都是互相不同的,后面我再对比一下Java的不同之处.
    我也不是用大量的例子来测试的,所以可能存在不准确的地方,请指正,共同进步.

    总结一下:

    C#里面 重载,继承的情况下方法的访问顺序

    1.类型的本身方法

    2.继承方法

    3.多态系方法

    如果是满足多态的情就简单,表现多态就行了。

  • 相关阅读:
    Manachar’s Algorithm
    脑裂 CAP PAXOS 单元化 网络分区 最终一致性 BASE
    Scheduling Multithreaded Computations by Work Stealing
    QQ好友状态,QQ群友状态,究竟是推还是拉? 网页端收消息,究竟是推还是拉?
    支持 gRPC 长链接,深度解读 Nacos 2.0 架构设计及新模型
    0到1:微信后台系统的演进之路 原创 张文瑞 InfoQ 2016-01-14
    救火必备!问题排查与系统优化手册
    如何紧急定位线上内存泄露? 原创 朱云锋 阿里技术 2019-12-20
    如何应对C语言内存泄露! 华为开发者社区 2020-09-29
    一次I/O问题引发的P0重大故障[改版重推] 原创 二马读书 二马读书 8月16日 这是前段时间发的一篇文章,很多读者反馈,文章没有揭示故障发生的详细
  • 原文地址:https://www.cnblogs.com/gw2010/p/3468819.html
Copyright © 2011-2022 走看看