有些中级开发小伙伴还是搞不太明白在继承父类以及不同场景实例化的情况下,父类和子类的各种方法的执行顺序到底是什么,下面通过场景的举例来重新认识下方法的执行顺序:

(下面内容涉及到了C#中的继承,构造函数,虚方法,虚方法的重写,new关键字等知识点)

场景一

有子类继承,但是只实例化父类:只执行A对象,输出A对象的信息

class A
{
public A() => Console.WriteLine("A的构造函数");
public virtual void Fun() => Console.WriteLine("A的方法");
}
class B : A
{
public B() => Console.WriteLine("B的构造函数");
public void Fun() => Console.WriteLine("B的方法");
}
class Program
{
static void Main(string[] args)
{
A a = new A();
a.Fun();
Console.ReadLine();
}
}

上述Main方法中在new A对象时,程序首先进入class A中,执行class A的构造函数A(),然后执行class A中的Fun()方法,故运行结果为:

场景二

实例化子类,子类和父类的构造函数的执行顺序:当执行B对象时,因为继承A对象,所以首先执行基类A的构造函数

class A
{
public A() => Console.WriteLine("A的构造函数");
public virtual void Fun()=> Console.WriteLine("A的方法");
}
class B : A
{
public B() => Console.WriteLine("B的构造函数");
public void Fun() => Console.WriteLine("B的方法");
}
class Program
{
static void Main(string[] args)
{
B b = new B();
b.Fun();
Console.ReadKey();
}
}

上述Main方法中在new B对象时,由于B继承A,先执行父类的构造函数,所以先执行A中的构造函数A(),然后在执行B中的构造函数B(),故运行结果为:

场景三

父类有虚方法,子类没有使用(override)关键字重写父类方法的时候,使用的是new关键字时:

class A
{
public A()=> Console.WriteLine("A的构造函数");
public virtual void Fun() => Console.WriteLine("A的方法"); }
class B : A
{
public B() => Console.WriteLine("B的构造函数");
//不写new时,该方法会抛出警告,但不是错误
public new void Fun()=> Console.WriteLine("B的方法");
}
class Program
{
static void Main(string[] args)
{
A a = new B();
a.Fun();
Console.ReadKey();
}
}

上述Main方法中先new B对象,先执行A中的构造函数A(),然后在执行B中的构造函数B(),最后调用class A的Fun()方法(没有重写父类方法),故运行结果为:

场景四

父类有虚方法, 当子类重写了(override)父类的方法时:

class A
{
public A()=> Console.WriteLine("A的构造函数");
public virtual void Fun() => Console.WriteLine("A的方法");
}
class B : A
{
public B()=> Console.WriteLine("B的构造函数");
public override void Fun()=> Console.WriteLine("B的方法");
}
static void Main(string[] args)
{
A a = new B();
a.Fun();
Console.ReadKey();
}

上述Main方法同样是先new B对象,先执行A中的构造函数A(),然后在执行B中的构造函数B(),但是子方法中使用了override关键字“覆盖”,使得子类中方法覆盖了父类中的方法,无法再访问父类中原始方法。(要重写方法,父类方法必须有virtual关键字),所以其运行结果为:

场景五

基类是接口层,多重继承时:

interface I
{
void Fun();
}
class A : I
{
public A() => Console.WriteLine("A的构造函数");
public virtual void Fun() => Console.WriteLine("A的方法");
}
class B : A
{
public B() => Console.WriteLine("B的构造函数");
//不写new时,该方法会抛出警告
public new void Fun() =>Console.WriteLine("B的方法");
}
static void Main(string[] args)
{
B b = new B();
b.Fun();
((A)b).Fun();
((I)b).Fun();
Console.ReadKey();
}

打印结果:

场景六

当多重继承,子类重写override父类方法时:

interface I
{
void Fun();
} class A : I
{
public A() => Console.WriteLine("A的构造函数");
public virtual void Fun() => Console.WriteLine("A的方法"); }
class B : A
{
public B() => Console.WriteLine("B的构造函数");
public override void Fun() =>Console.WriteLine("B的方法");
}
static void Main(string[] args)
{
B b = new B();
b.Fun();
((A)b).Fun();
((I)b).Fun();
Console.ReadKey();
}

打印结果:(对比场景5)

场景七

使用new重写父类方法,同时让每个子类都继承接口:

interface I
{
void Fun();
} class A : I
{
public A() => Console.WriteLine("A的构造函数");
public virtual void Fun() => Console.WriteLine("A的方法"); }
class B : A, I
{
public B() => Console.WriteLine("B的构造函数");
//不写new时,该方法会抛出警告
public new void Fun() => Console.WriteLine("B的方法");
}
static void Main(string[] args)
{
B b = new B();
b.Fun();
((A)b).Fun();
((I)b).Fun();
Console.ReadKey();
}

打印结果:

C#类中方法的执行顺序的更多相关文章

  1. 2018.11.20-day22 类中代码的执行顺序&组合

    1.类中代码的执行顺序 2.组合

  2. Java组合与继承生成的类中构造函数的执行顺序

    [程序实例] import java.util.*; class Meal{ Meal() { System.out.println("Meal Constructor"); } ...

  3. Java类中代码的执行顺序 静态代码块>构造代码块>构造方法

    一:静态代码块 注意是代码块,不是静态函数.函数要调用才执行,代码块加载就执行,一般是静态变量的声明与初始化.被static修饰的代码块(赋值.输出操作等).类中静态语句块仅在类加载时被执行一次 如 ...

  4. Java中,类与类,类中的代码执行顺序

    代码的执行顺序如下: 1.一个类的静态代码块.构造代码块.构造方法的执行流程为: 静态代码块 > 构造代码块 > 构造方法 2.静态的内容是随着类的加载而加载,静态代码块的内容会优先执行 ...

  5. java类中属性优先执行顺序

    1.父类静态代码块 (  java虚拟机加载类时,就会执行该块代码,故只执行一次) 2 .子类静态代码块 (  java虚拟机加载类时,就会执行该块代码,故只执行一次) 3. 父类属性对象初始化 4. ...

  6. Java:面向对象(继承,方法的重写(overide),super,object类及object类中方法的重写,父子类代码块执行顺序)

    继承: 1.继承是对某一匹类的抽象,从而实现对现实世界更好的建模. 2.提高代码的复用性. 3.extends(扩展),子类是父类的扩展. 4.子类继承父类可以得到父类的全部属性和方法.(除了父类的构 ...

  7. 在Spring Bean的生命周期中各方法的执行顺序

    Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,常用的设定方式有以下十种: 通过实现 InitializingBe ...

  8. hadoop27---netty中handler的执行顺序

    Netty是基于Java NIO的网络应用框架. Netty是一个NIO client-server(客户端服务器)框架,使用Netty可以快速开发网络应用,例如服务器和客户端协议.Netty提供了一 ...

  9. 7.Netty中 handler 的执行顺序

    1.Netty中handler的执行顺序 Handler在Netty中,无疑占据着非常重要的地位.Handler与Servlet中的filter很像,通过Handler可以完成通讯报文的解码编码.拦截 ...

随机推荐

  1. 什么是一致性hash?

    一致性hash 前言 说出来大家可能不相信,我昨天做梦梦到自己在面试,然后面试官问了我这个问题哈哈~然后我就打算按照自己的理解写一写.如果有写的不对的欢迎大家指正! 直接开始 普通hash算法 普通h ...

  2. Kubernetes,kubectl常用命令详解

    kubectl概述 祭出一张图,转载至 kubernetes-handbook/kubectl命令概述 ,可以对命令族有个整体的概念. 环境准备 允许master节点部署pod,使用命令如下: kub ...

  3. 文件连接--ln

    ln -n file1 file2  将文件2设置为文件1的软连接:file1和file2 任何一个改动都会反馈到另一方,删除源文件, 软连接文件不可用 ln -s file1 file2  将文件2 ...

  4. 【洛谷】P1294 高手去散步

    题目背景 高手最近谈恋爱了.不过是单相思."即使是单相思,也是完整的爱情",高手从未放弃对它的追求.今天,这个阳光明媚的早晨,太阳从西边缓缓升起.于是它找到高手,希望在晨读开始之前 ...

  5. 强大的 Guava 工具类

    Java 开发的同学应该都使用或者听说过 Google 提供的 Guava 工具包.日常使用最多的肯定是集合相关的工具类,还有 Guava cache,除了这些之外 Guava 还提供了很多有用的功能 ...

  6. Java性能优化的十条小技巧

    1 System.nanoTime 测试性能时,System.nanoTime比System.currentTimeMills更精确,前者使用纳秒计时,且对系统影响更小. 具体来说: System.c ...

  7. Apache配置虚拟目录+Zend Studio访问

    1 概述 Apache配置虚拟目录,然后可以通过Zend Studio的工程去访问,只需要修改Apache的httpd.conf文件. 2 修改httpd.conf 找到Apache安装目录下的htt ...

  8. (二十)VMware Harbor - API

    可以用swagger在线解析 http://editor.swagger.io/将swagger.yaml中的内容拷贝到里面即可. 官方文档说明链接如下:https://github.com/vmwa ...

  9. Django 模板(Template)

    1. 模板简介 2. 模板语言 DTL 3. 模板继承 4. HTML 转义 5. CSRF 1. 模板简介 作为 Web 开发框架,Django 提供了模板,可以很便利的动态生成 HTML.模版系统 ...

  10. 分布式锁的实现之 redis 篇

    为什么需要分布式锁 引入经典的秒杀情景,100件商品供客户抢.如果是单机版的话,我们使用synchronized 或者 lock 都可以实现线程安全.但是如果多个服务器的话,synchronized ...