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

(下面内容涉及到了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. c++一些概念

    面向对象语言三大特征: 封装,多态,继承 封装: 1.将函数定义到结构体内部,就是封装. 2.编译器会自动传递结构体的指针给函数. 类: 带有函数的结构体,称为类. 成员函数: 结构体里面的函数,称为 ...

  2. 跟我一起学Go系列:从写测试用例开始仗剑走天涯

    从入门到深入 Go 我们已经走了很长的路,当你想启动多个测试类的时候你是不是想启动多个 main 方法,但是 Go 限制了在同一个 package 下只能有一个 main,所以这条路你是走不通的.那我 ...

  3. 如何查看spark版本

    使用spark-shell命令进入shell模式

  4. Searching the Web UVA - 1597

      The word "search engine" may not be strange to you. Generally speaking, a search engine ...

  5. Day05_20_Java中类的创建和对象的实例化

    类的创建和对象的实例化 类的定义 类属于引用数据类型,java语言中所有的.class都属于引用数据类型 在类体当中,方法体之外定义的变量被称为 成员变量,成员变量没有赋值,系统默认是0: 语法结构: ...

  6. linux中mysql连接不上,服务启动失败等问题解决

    confluence问题解决方式 1)针对confluence访问页面报500与连接失败等问题 首先我们登陆部署confluence的服器 10.15.4.115 2)重启mysql服务,发现重启失败 ...

  7. PTA沈师数据库原理——DB(10)_SQL实验题

    R10-1 A1-3查询顾客表中所有不重复的城市 (2 分) select distinct Cityfrom customersR10-2 查询学生表所有学生记录 (2 分) select * fr ...

  8. SpringCloud(五)GateWay网关

    Config 分布式配置中心 概述 微服务意味着要将单体应用中的业务拆分成个个子服务,每个服务的粒度相对较小因此系统中会出现大量的服务 由于每个服务都需要必要的配置信息才能运行,所以一套集中式的.动态 ...

  9. Netty 框架学习 —— 第一个 Netty 应用

    概述 在本文,我们将编写一个基于 Netty 实现的客户端和服务端应用程序,相信通过学习该示例,一定能更全面的理解 Netty API 该图展示的是多个客户端同时连接到一台服务器.客户端建立一个连接后 ...

  10. 用vue-cli3搭建vue项目

    1.在nodejs官网下载node安装包,并进行安装:http://nodejs.cn/download/,在环境变量进行配置,并添加node_global和node_cache路径. 2.在D盘新建 ...