深入理解C#之继承

作者:佳园 时间:2022-02-25 07:25:44 

C#之继承

继承、封装和多态是面向对象编程的重要特性。

其成员被继承的类叫基类也称父类,继承其成员的类叫派生类也称子类。

派生类隐式获得基类的除构造函数和析构函数以外的所有成员。派生类只能有一个直接基类,所以C#并不支持多重继承,但一个基类可以有多个直接派生类。

继承是可以传递的。

即:如果 ClassB 派生出 ClassCClassA 派生出 ClassB,则 ClassC 会继承 ClassB ClassA 中声明的成员。


class A
   {
       public void Sum(int i,int j)
       {
           int sum = i + j;
           Console.WriteLine("I am A ,my sum ={0}",sum);
       }
   }
   class B : A
   {
       public void Minus(int i,int j)
       {
           int minus = i - j;
           Console.WriteLine("I am B ,my minus ={0}", minus);
           this.Sum(3, 4);
       }
   }
   class InheritanceTest1
   {
       static void Main(string[] args)
       {
           B b = new B();
           b.Minus(3, 4);
           Console.Read();
       }
   }

结果:

I am B ,my minus=-1

I am A ,my sum = 7

试想一下,当基类Sum()方法是私有时,派生类还会继承该方法吗?

经过本人测试,没有在B类找到该方法,那么是不是它就没有被继承呢?其实不是的,私有成员其实已经被继承了,但是它们却不可以被访问,因为私有成员只能被声明它们的类或结构体中才可访问,所以看上去像是没有被继承。

如果我们想降低访问基本,我们可以把基类Sum()方法定义为protected

能够阻止某个类被其他类继承吗?

答案是可以的,C#提供了一个sealed 修饰符,此修饰符会阻止其他类从该类继承。


  sealed class A
   {
       int test;
       public void Sum(int i,int j)
       {
           int sum = i + j;
           Console.WriteLine("I am A ,my sum ={0}",sum);
       }
   }
   class B : A
   {
       public void Minus(int i,int j)
       {
           int minus = i - j;
           Console.WriteLine("I am B ,my minus ={0}", minus);
           this.Sum(3, 4);       //编译器会报错    
       }
    }

前面说过,派生类隐式获得基类的除构造函数和析构函数以外的所有成员。

那么我们该如何获得基类的构造函数和自身的构造函数呢?

我们知道基类的初始化工作由基类的构造函数完成,派生类的初始化工作则有派生类的构造函数完成,但是这样就产生了派生类构造函数的执行顺序问题。

当基类没有构造函数,派生类也没有构造函数时,派生类新曾成员的初始化工作由其他公有函数来完成。


public  class A
   {
       int test=0;
       public void sum()
       {
           test++;
           Console.WriteLine("I am test ={0}" ,test);
       }
   }
   class B : A
   {
       int i;
       public void PrintInt()
       {
           i = 3;
           Console.WriteLine("I am i ={0}", i);
       }
   }
   class InheritanceTest1
   {
       static void Main(string[] args)
       {
           B b = new B();
           b.PrintInt();
           Console.Read();
       }
   }

结果:

I am i=3

如果只有派生类定义构造函数时,只需构造派生类对象即可。对象的基类部分使用默认构造函数来自动创建。当基类和派生类

都定义有构造函数时,那么执行顺序会怎样呢?

如果基类中是没有参数的构造函数,那么他可以隐式的被派生类执行,也就是说,派生类根本不需要包含构造函数如果基类中是没有参数的构造函数,在派生类中可以自定义有参数的构造函数publicclassA


public  class A
   {
       int test=0;
       public A()
       {
           test = 5;
           Console.WriteLine("I am A 公有默认构造函数 ,test={0}", test);
       }
   }
   class B : A
   {
   }
   class InheritanceTest1
   {
       static void Main(string[] args)
       {
           B b = new B();
           Console.Read();
       }
   }

结果:

I am A 公有默认构造函数 ,test=5

由此可以看见,基类的构造函数被执行,在派生类中被调用。

如果基类定义了带有参数的构造函数,那么此构造函数必须被执行,且在派生类中实现该构造函数,此时我们可以使用base关键字


  class A
   {
       int test=0;
       public A(int i)
       {
           test = i;
           Console.WriteLine("I am A 公有有参构造函数 ,test={0}", test);
       }
   }
   class B : A
   {
       public B(int j):base(j)
       {
           Console.WriteLine("I am B 公有有参构造函数,j={0}",j);
       }
   }
   class InheritanceTest1
   {
       static void Main(string[] args)
       {
           B b = new B(1);
           Console.Read();
       }
   }

结果:

I am A 公有有参构造函数 ,test=1

I am B 公有有参构造函数,j=1

由此可见: 派生类隐式执行基类中带有参数的构造函数,在程序中基类定义了带有参数的构造函数,在其派生类中被继承,并使用base关键字调用基类中的构造函数来传送参数。

我们可以从代码中看到在创建派生类的对象后,程序首先运行的是基类的构造函数中的内容,然后才是派生类中的内容。

如果派生类的基类也是派生类,则每个派生类只需负责其直接基类的构造,不负责间接基类的构造,并且其执行构造函数的顺序是从最上面的基类开始的,直到最后一个派生类结束。

来源:https://www.cnblogs.com/jiajiayuan/archive/2011/09/09/2172292.html

标签:C#,继承
0
投稿

猜你喜欢

  • 教你如何监控 Java 线程池运行状态的操作(必看)

    2023-02-09 04:34:13
  • C#实现自定义windows系统日志的方法

    2021-12-17 13:02:31
  • java实现死锁的示例代码

    2023-10-12 18:12:40
  • openFeign服务之间调用保持请求头信息处理方式

    2022-11-07 23:45:21
  • Java利用Phantomjs实现生成图片的功能

    2022-01-17 08:21:25
  • tcp、udp、ip协议分析_动力节点Java学院整理

    2023-05-17 18:00:17
  • 基于Unity3D实现3D照片墙效果

    2023-05-22 00:18:51
  • Kotlin中空判断处理操作实例

    2023-01-16 00:45:19
  • Android 遍历SDCARD的文件夹并显示目录信息

    2021-06-01 21:49:04
  • 亲自教你实现栈及C#中Stack源码分析

    2021-05-23 19:39:10
  • IDEA2020.1使用LeetCode插件运行并调试本地样例的方法详解

    2022-02-28 09:44:47
  • Android UI设计系列之自定义ListView仿QQ空间阻尼下拉刷新和渐变菜单栏效果(8)

    2023-05-23 14:57:04
  • C# 获取本机IP地址(IPv4和IPv6)

    2023-09-04 08:48:36
  • Java实现打字游戏

    2021-11-02 16:46:56
  • Android仿微信录制语音功能

    2022-10-18 15:54:18
  • C#采用mouse_event函数实现模拟鼠标功能

    2023-07-07 16:09:54
  • java8 stream 如何打印数据元素

    2022-08-20 18:40:02
  • C#多线程等待所有子线程结束的示例

    2021-07-02 23:04:57
  • jdbc中class.forname的作用

    2023-04-13 00:56:18
  • Android中文件读写(输入流和输出流)操作小结

    2023-07-23 02:53:19
  • asp之家 软件编程 m.aspxhome.com