C# 多态 派生类 abstract virtual new

  • 静态多态
    • 函数重载
    • 运算符重载
  • 动态多态
    • abstract 和 virtual的区别
      • 定义与用途:
      • 成员实现:
      • 继承与重写:
      • 与接口的区别:
    • 使用抽象类的好处主要体现在以下几个方面:
      • 代码重用:
      • 设计灵活性:
      • 接口定义:
      • 类型安全:
      • 易于扩展和维护:
      • 符合面向对象的设计原则:
      • 综上所述,
  • 派生类中调用基类成员
      • 通过base关键字调用:
      • 直接调用:
      • 通过构造函数:
  • 在C#中,new关键字有多个用途
      • 对象实例化:
      • 隐藏基类成员:
      • 约束:
      • 运算符重载:
      • 初始化数组:
      • 随对象一起初始化字段:
  • 例子

静态多态

在编译时,函数和对象的连接机制被称为早期绑定,也被称为静态绑定。C# 提供了两种技术来实现静态多态性。分别为:

函数重载

同名不同参

运算符重载

动态多态

C# 允许您使用关键字 abstract 创建抽象类,用于提供接口的部分类的实现。当一个派生类继承自该抽象类时,实现即完成。抽象类包含抽象方法,抽象方法可被派生类实现。派生类具有更专业的功能。

请注意,下面是有关抽象类的一些规则:

您不能创建一个抽象类的实例。
您不能在一个抽象类外部声明一个抽象方法。
通过在类定义前面放置关键字 sealed,可以将类声明为密封类。当一个类被声明为 sealed 时,它不能被继承。抽象类不能被声明为 sealed

总之,
类前声明abstruct就可以写出一个抽象类

当有一个定义在类中的函数需要在继承类中实现时,可以使用虚方法。
虚方法是使用关键字 virtual 声明的。
虚方法可以在不同的继承类中有不同的实现。
对虚方法的调用是在运行时发生的。
动态多态性是通过 抽象类 和 虚方法 实现的。

在C#(以及其他一些面向对象的编程语言中),override是一个关键字,用于指示一个方法在派生类中覆盖了基类中的同名方法。这意味着,当你使用派生类的对象并调用这个方法时,将执行派生类中的版本,而不是基类中的版本。

要使用override关键字,必须满足以下条件

基类中存在一个虚方法(virtual)或抽象方法(abstract):基类中必须有一个具有相同签名(即相同的名称、参数列表和返回类型)的虚方法或抽象方法。

派生类继承自基类:包含override方法的类必须是从包含被覆盖方法的类继承而来的。

方法签名匹配:派生类中的方法必须与基类中被覆盖的方法具有相同的签名。

访问修饰符不能比基类方法更严格:派生类中方法的访问修饰符(如publicprotectedinternal)不能比基类中被覆盖的方法更严格。例如,如果基类中的方法是public的,那么派生类中的覆盖方法也必须是public的。

using System;
namespace PolymorphismApplication
{class Shape {protected int width, height;public Shape( int a=0, int b=0){width = a;height = b;}public virtual int area(){Console.WriteLine("父类的面积:");return 0;}}class Rectangle: Shape{public Rectangle( int a=0, int b=0): base(a, b){}public override int area (){Console.WriteLine("Rectangle 类的面积:");return (width * height); }}class Triangle: Shape{public Triangle(int a = 0, int b = 0): base(a, b){}public override int area(){Console.WriteLine("Triangle 类的面积:");return (width * height / 2); }}class Caller{public void CallArea(Shape sh){int a;a = sh.area();Console.WriteLine("面积: {0}", a);}}  class Tester{static void Main(string[] args){Caller c = new Caller();Rectangle r = new Rectangle(10, 7);Triangle t = new Triangle(10, 5);c.CallArea(r);c.CallArea(t);Console.ReadKey();}}
}

abstract 和 virtual的区别

C#中,abstractvirtual是两个用于类和成员修饰的关键字,它们各自有着特定的用途和区别。

定义与用途:

abstract关键字用于定义抽象类和抽象成员(包括方法、属性、索引器、事件)。抽象类是一种特殊的类,不能被实例化,只能被其他类继承。抽象成员在抽象类中没有具体的实现,必须在派生类中提供实现。
virtual关键字用于定义虚方法、虚属性、虚索引器或虚事件。虚成员可以在派生类中被重写(override)。这意味着派生类可以提供该成员的不同实现。

成员实现:

abstract修饰的方法或属性不能有实现,它们只是声明了一个约定,具体的实现必须在派生类中完成。
virtual修饰的方法或属性必须有方法实现(哪怕只有一对大括号)。派生类可以选择是否重写虚成员。

继承与重写:

如果一个类包含抽象方法,那么这个类必须被声明为抽象类。抽象方法必须在任何非抽象派生类中被重写。
虚方法可以被任何继承它的类重写,但不是必须的。如果派生类没有重写虚方法,那么将使用基类中的实现。

与接口的区别:

抽象类是对对象的抽象,可以包含抽象方法和非抽象方法,是对一组具有共同特征的对象的抽象。它不能被实例化,但可以通过继承来创建具体的对象。
接口是一种行为规范,只包含抽象方法和事件的声明,不包含任何实现。任何实现接口的类都必须提供接口中所有方法的实现。
总的来说,abstractvirtualC#中都是用于实现多态性的重要机制,但它们在定义、实现、继承与重写方面有着明显的区别。abstract更强调强制派生类提供实现,而virtual则提供了一种可选的重写机制。

使用抽象类的好处主要体现在以下几个方面:

代码重用:

抽象类允许我们定义一组通用的方法和属性,这些方法和属性可以被多个派生类共享。通过继承抽象类,派生类可以自动获得这些通用方法和属性的实现,从而避免了在每个派生类中重复编写相同的代码。

设计灵活性:

抽象类为设计提供了更大的灵活性。通过将某些方法或属性声明为抽象成员(即没有具体实现的方法或属性),我们可以强制派生类提供这些成员的具体实现。这有助于确保派生类遵循一定的接口或协议,从而实现更加一致和可预测的行为。

接口定义:

抽象类可以作为接口的一种实现方式。与纯接口相比,抽象类可以包含部分实现,使得某些通用的功能可以在抽象类中实现,而派生类只需关注特定于它们自己的实现。

类型安全:

通过抽象类,我们可以限制哪些类可以作为派生类。只有实现了抽象类中所有抽象成员的类才能被实例化。这有助于确保类型安全,防止不正确的类继承和使用。

易于扩展和维护:

当需要添加新的功能或修改现有功能时,我们只需在抽象类中进行相应的更改,所有继承该抽象类的派生类都将自动获得这些更改。这大大简化了代码的扩展和维护过程。

符合面向对象的设计原则:

使用抽象类有助于遵循面向对象的设计原则,如开闭原则(对扩展开放,对修改封闭)和里氏替换原则(子类必须能够替换其基类)。这些原则有助于构建更加健壮、可维护和可扩展的软件系统。

综上所述,

使用抽象类可以提高代码的重用性、设计灵活性、类型安全性以及易于扩展和维护性,同时也有助于遵循面向对象的设计原则。

派生类中调用基类成员

在派生类中调用基类成员的方法取决于成员的类型(字段、属性、方法)以及成员的访问修饰符。以下是几种常见的方式来在派生类中调用基类成员:

通过base关键字调用:

当派生类需要访问或调用被覆盖(override)的基类方法或属性时,可以使用base关键字来引用基类中的成员。
base关键字用于访问基类的构造函数、字段、属性、方法等。

public class BaseClass  
{  public void BaseMethod()  {  Console.WriteLine("This is the base method.");  }  
}  public class DerivedClass : BaseClass  
{  public new void BaseMethod() // 注意这里使用了new关键字来隐藏基类方法  {  base.BaseMethod(); // 调用基类中被覆盖的方法  Console.WriteLine("This is the derived method.");  }  
}

直接调用:

如果派生类没有覆盖基类的成员,那么可以直接调用这些成员,而无需使用base关键字。

public class DerivedClass : BaseClass  
{  public void CallBaseMethod()  {  BaseMethod(); // 直接调用基类方法  }  
}

通过构造函数:

在派生类的构造函数中,可以使用base关键字来调用基类的构造函数。

public class BaseClass  
{  public BaseClass()  {  Console.WriteLine("BaseClass constructor called.");  }  
}  public class DerivedClass : BaseClass  
{  public DerivedClass() : base() // 调用基类的构造函数  {  Console.WriteLine("DerivedClass constructor called.");  }  
}

请注意,如果基类成员是私有的(private),那么派生类无法直接访问它们。私有成员只能在定义它们的类内部被访问。如果基类成员是受保护的(protected),则派生类可以直接访问这些成员。如果基类成员是公共的(public)或受保护的,那么派生类可以像访问任何其他公共或受保护成员一样访问它们。

此外,当派生类使用new关键字隐藏基类中的成员时,虽然派生类成员和基类成员具有相同的名称,但它们实际上是两个不同的成员。在这种情况下,如果需要调用基类中被隐藏的成员,就必须使用base关键字。

在C#中,new关键字有多个用途

它们在不同上下文中具有不同的意义。以下是new关键字在C#中的一些主要用途:

对象实例化:

最常见的用法是创建对象实例。例如:

MyClass myObject = new MyClass();

这里,new MyClass()用于调用MyClass的构造函数并创建该类的一个新实例。

隐藏基类成员:

当在派生类中定义与基类成员同名的成员时,可以使用new关键字来显式地表示派生类成员隐藏了基类成员。这样做通常是为了避免基类成员的意外调用。

class Base  
{  public void MyMethod() { /* ... */ }  
}  class Derived : Base  
{  public new void MyMethod() { /* ... */ }  
}

在这个例子中,Derived类中的MyMethod隐藏了Base类中的MyMethod

约束:

在泛型类、接口或方法的定义中,new()约束用于指定类型参数必须具有无参数的公共构造函数。

public class MyClass<T> where T : new()  
{  public T CreateInstance()  {  return new T();  }  
}

这里,new()约束确保T类型有一个无参数的构造函数,因此可以在CreateInstance方法中创建它的实例。

运算符重载:

new运算符也可以被重载以用于自定义类型。这通常与资源管理和释放相关,尤其是在实现IDisposable接口时。但是,直接重载new运算符并不常见,因为C#提供了更具体的语法来管理资源(如using语句)。

初始化数组:

new用于创建数组实例,并可以初始化数组元素。

int[] myArray = new int[5] { 1, 2, 3, 4, 5 };

这里,new int[5]创建一个包含5个整数的数组,并通过花括号中的值进行初始化。

随对象一起初始化字段:

在对象实例化时,可以使用对象初始化器语法与new一起初始化对象的字段或属性。

var person = new Person  
{  Name = "Alice",  Age = 30  
};

这里,new Person创建了一个Person对象,并使用对象初始化器语法设置了NameAge属性。

请注意new关键字的具体行为取决于它在哪里以及如何被使用。在使用new时,应确保你了解其当前上下文中的确切意义,以避免潜在的错误或混淆。

例子

using System;class TODO {static void Main() {Console.Write("Hello C#!\n");Tools tools = new Tools();int ans = tools.add(1, 2);Console.WriteLine(ans);Cars chaos = new Cars();Console.WriteLine("this thing is {0}.", chaos.SayName());chaos.x = 1;chaos.y = 2;chaos.z = 3;Console.WriteLine(chaos.Area());}
}class Tools {public int add(int x, int y) { return x + y; }public int add(int x, int y, int z) { return x + y + z; }
}abstract class Boxs {public int x;public int y;public int z;public int Area() {return x * y * x;}abstract public string SayName();virtual public void SayHello() { System.Console.Write("Hello!\n"); }private int total;
}class Cars: Boxs {public override string SayName() { return "CAR";  }public override void SayHello() {base.SayHello();}public new int Area() {return x + y + z;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/777260.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HCIP作业3

第一步 给PC1配置&#xff1a; 先给PC2配置&#xff1a; 第二部 给R1的接口配置ip [R1]int g0/0/0 [R1-GigabitEthernet0/0/0]ip add 192.168.1.252 24 [R1-GigabitEthernet0/0/0]int g0/0/1 [R1-GigabitEthernet0/0/1]ip ad 100.1.1.1 24 给R2的接口配置IP [R2]int g0/0/…

Java:接口应用(Comparable接口与比较器)

目录 1.引例2.Comparable接口使用3.Comparable接口的局限性4.使用comparaTo实现排序5.比较器&#xff08;Comparator接口&#xff09; 1.引例 class Student{private String name;private int age;public Student(String name, int age) {this.name name;this.age age;} } p…

#孩子学习编程的目的是什么?#

谢谢今日头条编辑的盛情邀请&#xff0c;对此&#xff0c;我发表自己的一点拙见。 首先&#xff0c;最重要的一点&#xff0c;学习编程可以练习打字&#xff0c;加强拼音输入法的掌握。对于孩子的语文成绩有一定的提高帮助&#xff0c;也为将来走上工作熟练使用电脑输入法打下扎…

Linux的学习之路:3、基础指令(2)

一、echo指令 这个指令在上篇文章我也用了但是忘了说了&#xff0c;这个指令的大概用法就是把后面跟的文本等输出在显示器上&#xff0c;如下代码所示打印的“Hello Linux” [rootVM-24-9-centos ~]# echo "Hello Linux" Hello Linux二、输出重定向与输入重定向 着…

vue页面实现左右div宽度,上下div高度分割线手动拖动高度或者宽度自动变化,两个div宽度或者高度拉伸调节,实现左右可拖动改变宽度的div内容显示区

实现左右或者上下div两部分拖动&#xff0c;宽度或者高度自动变化,实现流畅平滑的变化&#xff0c;还可以是实现拖动到一定宽度就不让拖动了&#xff0c;如果你不需要最小宽度&#xff0c;就直接去掉样式就行 这是页面。分左中右三部分&#xff0c;中间我是用来作为拖动的按钮…

Java实现猜数字游戏:编程入门之旅

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

Java研学-SpringBoot(三)

五 Spring Boot 自动配置原理 1 概念 springboot的自动装配就是从spring.factories文件中获取到对应的需要进行自动装配的类&#xff0c;并生成相应的Bean对象&#xff0c;然后将它们交给spring容器来帮我们进行管理。核心注解&#xff1a;SpringBootApplication   调用main…

使用 Yoda 和 ClickHouse 进行实时欺诈检测

背景 Instacart 是北美领先的在线杂货公司,拥有数百万活跃的客户和购物者。在其平台上打击欺诈和滥用行为不仅对于维护一个值得信赖和安全的环境至关重要,也对保持Instacart的财务健康至关重要。在这篇文章中,将介绍了一个欺诈平台——Yoda,解释了为什么我们选择ClickHous…

奖学金NOIP2007 普及组 T1

题目背景 NOIP2007 普及组 T1 题目描述 某小学最近得到了一笔赞助&#xff0c;打算拿出其中一部分为学习成绩优秀的前 55 名学生发奖学金。期末&#xff0c;每个学生都有 33 门课的成绩&#xff1a;语文、数学、英语。先按总分从高到低排序&#xff0c;如果两个同学总分相同…

Linux 反引号、单引号以及双引号的区别

1.单引号—— 单引号中所有的字符包括特殊字符&#xff08;$,,和\&#xff09;都将解释成字符本身而成为普通字符。它不会解析任何变量&#xff0c;元字符&#xff0c;通配符&#xff0c;转义符&#xff0c;只被当作字符串处理。 2.双引号——" 双引号&#xff0c;除了$,…

Android 14.0 SystemUI下拉状态栏增加响铃功能

1.概述 在14.0的系统产品rom定制化开发中,在对systemui的状态栏开发中,对SystemUI下拉状态栏的QuickQSPanel区域有快捷功能键开关,对于增加各种响铃快捷也是常用功能, 有需要增加响铃功能开关功能,接下来就来分析SystemUI下拉状态栏QuickQSPanel快捷功能键开关的相关源码…

API接口开发亚马逊国际获得AMAZON商品详情api采集商品详情页实时数据、实时销量、库存等参数接入演示

要获取亚马逊商品的实时数据、销量和库存等信息&#xff0c;您需要使用亚马逊提供的一些API接口。以下是一些可能的步骤&#xff1a; 注册key账号&#xff1a;首先&#xff0c;您需要注册一个账号。这将允许您访问亚马逊的各种API。 创建一个新的应用&#xff1a;在您的开发者…

AI智能分析网关智慧食安监管系统方案

3.15晚会刚过不久&#xff0c;淀粉肠的“屈辱”终于得以洗清&#xff0c;但某些品牌奶茶、梅菜扣肉、预制菜等等&#xff0c;生产过程仍是触目惊心。如何提升食品安全管理水平&#xff0c;保障食品从生产到消费环节的质量和安全&#xff1f;TSINGSEE青犀智利用智能分析网关V4Ea…

【图像合成】基于DCGAN典型网络的MNIST字符生成(pytorch)

关于 近年来&#xff0c;基于卷积网络&#xff08;CNN&#xff09;的监督学习已经 在计算机视觉应用中得到了广泛的采用。相比之下&#xff0c;无监督 使用 CNN 进行学习受到的关注较少。在这项工作中&#xff0c;我们希望能有所帮助 缩小了 CNN 在监督学习和无监督学习方面的成…

aws使用记录

数据传输&#xff08;S3) 安装命令行 安装awscli: https://docs.aws.amazon.com/zh_cn/cli/latest/userguide/getting-started-install.html#getting-started-install-instructions 直到 aws configure list 可以运行 身份验证&#xff1a; 运行&#xff1a; aws config…

字符计数.

题目描述 给定一个单词&#xff0c;请计算这个单词中有多少个元音字母&#xff0c;多少个辅音字母。 元音字母包括 a,e,i,o,u&#xff0c;共五个&#xff0c;其他均为辅音字母。 输入描述 输入格式 输入一行&#xff0c;包含一个单词&#xff0c;!单词中只包含小写英文字母。单…

【QGIS从shp文件中筛选目标区域导出为shp】

文章目录 1、写在前面2、QGIS将shp文件中目标区域输出为shp2.1、手动点选2.2、高级过滤 3、上述shp完成后&#xff0c;配合python的shp文件&#xff0c;即可凸显研究区域了 1、写在前面 利用shp文件制作研究区域mask&#xff0c;Matlab版本&#xff0c;请点击 Matlab利用shp文…

网络编程综合项目-多用户通信系统

文章目录 1.项目所用技术栈本项目使用了java基础&#xff0c;面向对象&#xff0c;集合&#xff0c;泛型&#xff0c;IO流&#xff0c;多线程&#xff0c;Tcp字节流编程的技术 2.通信系统整体分析主要思路&#xff08;自己理解&#xff09;1.如果不用多线程2.使用多线程3.对多线…

uniapp-Form示例(uviewPlus)

示例说明 Vue版本&#xff1a;vue3 组件&#xff1a;uviewPlus&#xff08;Form 表单 | uview-plus 3.0 - 全面兼容nvue的uni-app生态框架 - uni-app UI框架&#xff09; 说明&#xff1a;表单组建、表单验证、提交验证等&#xff1b; 截图&#xff1a; 示例代码 <templat…

3月28日,每日信息差

&#x1f384; 亚马逊未来15年或斥资1480亿美元在全球建设并运营数据中心 &#x1f30d; 中国移动正式商用5.5G 网络&#xff0c;Find X7系列成为首款5.5G手机 &#x1f30b; UC网盘官宣上传、下载不限速 &#x1f381; 优酷发布行业首款影视制作车 ✨ 阿里云联发科联手为手机芯…