(五)CSharp-继承

news/2025/2/18 10:48:54/

一、继承概念

继承类型分为两种: 实现继承和接口继承。

多重继承: 一个类派生自多个类。

C# 不支持多重实现继承,但允许多重接口继承。

结构不支持继承: 结构不支持实现继承,但是可以支持接口继承

  • 结构总是派生自 System.ValueType,它们还可以派生自任意多个接口。
  • 类总是派生自 System.Object 或用户选择的另一个类,它们还可以派生自任意多个接口。

二、对基类的访问和引用

基类访问

   class SomeClass{public string Field1 = "Field1 -- In the base class";}class OtherClass : SomeClass{new public string Field1 = "Field1 -- In the derived class";public void PrintField1(){Console.WriteLine(Field1); // 访问派生类Console.WriteLine(base.Field1); //访问基类}}class Program{static void Main(string[] args){OtherClass oc = new OtherClass();oc.PrintField1();Console.ReadKey();}}

使用基类的引用

class MyBaseClass{public void Print(){Console.WriteLine("This is the base class.");}}class MyDerivedClass : MyBaseClass{public int var1;new public void Print(){Console.WriteLine("This is the derived class.");}}class Program{static void Main(string[] args){MyDerivedClass derived = new MyDerivedClass();MyBaseClass mybc = (MyBaseClass)derived;derived.Print();mybc.Print();Console.ReadKey();}}

输出结果:

Field1 – In the derived class
Field1 – In the base class

三、虚方法

1、声明定义虚方法

把一个基类函数声明为 virtual,就可以在任何派生类中重写该函数。

    class MyBaseClass{//虚方法public virtual string VirualMethod(){return "This method is virtual and defined in MyBaseClass";}//虚属性public virtual string ForeName{get { return foreName; }set { foreName = value; }}private string foreName;}class MyDerivedClass : MyBaseClass{//使用 override 来 重写虚方法public override string VirualMethod(){return "This method is an override define in MyDerivedClass";}}class Program{static void Main(string[] args){MyDerivedClass derived = new MyDerivedClass();MyBaseClass mybc = (MyBaseClass)derived;Console.WriteLine(derived.VirualMethod());Console.WriteLine(mybc.VirualMethod());Console.ReadKey();}}

输出结果:

This method is an override define in MyDerivedClass
This method is an override define in MyDerivedClass

从结果可知,派生类转换为基类,其结果仍是调用派生类重写的虚方法。

2、调用函数的基类版本

若派生类在基类的基础上,对虚方法进行代码逻辑的补充时:

    class CustomerAccount{public virtual decimal CalculatePrice(){return 0.0M;}class GoldAccount : CustomerAccount{public override decimal CalculatePrice(){return base.CalculatePrice() * 90;}}}

3、虚方法小结:

  • 在 C# 中,函数在默认情况下不是虚拟的,但(除了构造函数以外)可以显式地声明为 virtual。
  • C# 要求在派生类的函数重写另一个函数,要使用 overiride 关键字显式声明。
  • 成员字段和静态函数都不能声明为 virual。
  • 虚方法不可用 private 修饰符

四、隐藏方法

如果在基类和派生类中,有签名相同的方法,但该方法没有分别声明为 virrual 和 override,派生类方法就会隐藏基类方法。

隐藏方法存在安全隐患: 由于派生类和基类使用的是相同签名的方法,但该方法执行的结果不相同。若程序员想要调用派生类的,但不小心调用的是基类的,该方法执行后会出现潜在程序的错误。

五、抽象类与抽象函数

  • C# 允许把类和函数声明为 abstract。
  • 抽象类不能实例化,抽象函数不能直接实现,必须在非抽象的派生类中重写。
  • 抽象函数本身也是虚拟的
  • 如果类包含抽象函数,则该类也是抽象的,也必须声明为抽象的。
abstract class Building
{
public abstract decimal CalculateHeatingCost();// abstract method
}

六、密封类和密封方法

C# 允许把类和方法声明为 sealead。对于类,这表示不能继承该类;对于方法(属性也可密封),这表示不能重写该方法。(密封方法,是否可以使得隐藏方法更加安全)

1、密封类:

 sealed class FinalClass{}//提示错误,密封类不能被继承class DerivedClass : FinalClass{}

2、密封方法

  class MyBaseClass1{public virtual void TestFun(){}}class FinalClass : MyBaseClass1{sealed public override void TestFun(){}}class DerivedClass : FinalClass{//提示错误,密封方法不能被重写//因为继承的这个基类设置该方法为密封方法public override void TestFun(){}}

七、可见性修饰符

表-修饰符的访问说明

修饰符应用于说明
public所有类或成员任何代码均可以访问该项
protected类型和内联类型的所有成员只有派生的类型能访问该项
internal所有类型或成员只能在包含它的程序集中访问该项
private类型和内联类型的所有成员只能在它所属的类型中访问该项
protected internal类型和内联类型的所有成员只能在包含它的程序集和派生类型的任何代码中访问该项

内嵌类型: 在类的内部再声明一个类

    public class OtherClass{private int id = 0;protected class InnerClass{public void InnerClassFun(){OtherClass oc = new OtherClass();oc.id = 0;//可访问}}}

表-成员可访问性总结(出自《C# 图解教程》-8.9.7 成员访问修饰符小结)

同一程序集内的类同一程序集内的类不同一程序集内的类不同一程序集内的类
非派生类派生类非派生类派生类
private
internal
protected
protected internal
public

其他修饰符

修饰符应用于说明
new函数成员成员用相同的签名隐藏继承的成员
staitc所有成员成员不作用于类的具体实例
virtual仅函数成员成员可以由派生类重写
abstract仅函数成员虚拟成员定义了成员的签名,但没有提供实现代码
override仅函数成员成员重写了继承的虚拟或抽象成员
sealed类、方法和属性对于类,不能继承自密封类。对于属性和方法,成员重写已继承的虚拟成员,但任何派生类中的任何成员都不能重写该成员。该修饰符必须与 override 一起使用
extern仅静态(DllImport)方法成员在外部用另一种语言实现

八、程序集间的继承

C# 允许从一个在不同的程序集内定义的基类来派生类。

要从不同程序集中定义的基类派生类,必须具备以下条件:

  • 基类必须被声明为 public,这样才能从它所在的程序集外部访问它。
  • 必须在 Viusal Studio 工程中的 Reference 节点中添加包含该基类的程序集的引用。

http://www.ppmy.cn/news/282244.html

相关文章

【软件测试】软件测试的基本概念和开发模型

1. 前言 在进行软件测试的学习之前,我们要了解软件测试一些基本概念. 这些基本概念将帮助我们更加明确工作的目标以及软件测试到底要做什么. 2. 软件测试的基本概念 软件测试的基本概念有3个,分别是需求,测试用例和BUG. 2.1 需求 这里的需求还可以分为 用户需求和软件需求,用户…

electron探索

windows上使用electron-builder打包 网络问题参考:electron-builder打包过程中报错——网络下载篇_wincodesign-2.6.0.7z_程序边界的博客-CSDN博客 linux上使用electron-builder打包 1. 需要的包因为网络问题下不下来 遇到fpm1.9.3-2.3.1-linux-x86在github上下…

python 爬虫之数据清洗

Python爬虫是一项强大的工具,可用于获取大量数据并进行分析和处理。但是,爬取的数据在处理之前需要经过清洗,以消除无用或无效的信息,并确保数据可靠和可用。在本文中,我们将详细讨论Python爬虫数据清洗的过程和技巧&a…

【博客647】MetricsQL(VictoriaMetrics)和PromQL(Prometheus)的不同之处

MetricsQL(VictoriaMetrics)和PromQL(Prometheus)的不同之处 1、如果对PromSQL不熟悉可以先看以下链接 https://valyala.medium.com/promql-tutorial-for-beginners-9ab455142085 2、与PromQL相比,以下功能在MetricsQL中的实现方式不同,这也改善了用户…

python3语音控制电脑_利用智能音箱语音控制电脑开关机

完成下面这个有趣的实验,你所需要的东西有: 路由器(能够形成局域网,且电脑已用网线连接) 一个智能音箱(本教程使用的是亚马逊 Echo Dot 2) 主板支持wake on lan (大部分都支持) 一个树莓派 原理流程图如下: 接下里将按照这个流程图…

使用 GMDH 进行时间序列预测

目录 主要命令 CreateTimeSeriesData FitPolynomial GetPolynomialLayer 分组数据处理方法(GMDH) PLOT 主要命令 采用分组数据处理方法(GMDH)对全球冰体积时间序列的建模和预测 fsz size(A) 返回一个行向量,其元…

软件测试(功能、接口、性能、自动化)详解

一、软件测试功能测试测试用例编写是软件测试的基本技能;也有很多人认为测试用例是软件测试的核心;软件测试中最重要的是设计和生成有效的测试用例;测试用例是测试工作的指导,是软件测试的必须遵守的准则。黑盒测试常见测试用例编…

如何将鼠标计算机配置放到板载,罗技G500S游戏鼠标配备有板载内存让鼠标脱离驱动实现自定义功能...

板载内存可将鼠标与驱动程序分开以实现自定义功能 尽管鼠标驱动程序可以实现许多便捷的功能,但是要实现这些功能,通常需要先安装驱动程序,然后让鼠标驱动程序驻留在内存中(在后台运行)以提供支持。对于某些经常从16K到128,可以直接…