当前位置: 首页 > news >正文

C# 继承、多态性、抽象和接口详解:从入门到精通

C# 继承

C# 中,可以将字段和方法从一个类继承到另一个类。我们将“继承概念”分为两类:

  • 派生类(子类) - 从另一个类继承的类
  • 基类(父类) - 被继承的类

要从一个类继承,使用 : 符号。

在以下示例中,Car 类(子类)继承了 Vehicle 类(父类)的字段和方法:

示例

class Vehicle  // 基类(父类)
{public string brand = "Ford";  // 车辆字段public void honk()             // 车辆方法{Console.WriteLine("Tuut, tuut!");}
}class Car : Vehicle  // 派生类(子类)
{public string modelName = "Mustang";  // 汽车字段
}class Program
{static void Main(string[] args){// 创建一个 myCar 对象Car myCar = new Car();// 在 myCar 对象上调用 honk() 方法(来自 Vehicle 类)myCar.honk();// 显示 brand 字段(来自 Vehicle 类)的值和 modelName 字段(来自 Car 类)的值Console.WriteLine(myCar.brand + " " + myCar.modelName);}
}

输出

Tuut, tuut!
Ford Mustang

为什么以及何时使用“继承”?

  • 它对于代码重用非常有用:在创建新类时重用现有类的字段和方法

sealed 关键字

如果您不希望其他类从一个类继承,请使用 sealed 关键字:

sealed class Vehicle 
{...
}class Car : Vehicle 
{...
}

如果您尝试访问一个 sealed 类,C# 会生成一个错误:

'Car': cannot derive from sealed type 'Vehicle'

多态性和方法覆盖

多态性意味着 “多种形态”,它发生在我们有许多通过继承相互关联的类时。继承允许我们从另一个类继承字段和方法。多态性使用这些方法来执行不同的任务。这允许我们以不同的方式执行单个动作。

例如,考虑一个名为 Animal 的基类,它有一个名为 animalSound() 的方法。Animal 的派生类可以是 PigsCatsDogsBirds,它们也有自己的 animalSound() 方法实现(猪会叫,猫会喵喵叫等)。

示例:

class Animal  // 基类(父类)
{public virtual void animalSound() {Console.WriteLine("动物发出声音");}
}class Pig : Animal  // 派生类(子类)
{public override void animalSound() {Console.WriteLine("猪说:wee wee");}
}class Dog : Animal  // 派生类(子类)
{public override void animalSound() {Console.WriteLine("狗说:bow wow");}
}

现在我们可以创建 PigDog 对象,并在它们两个上调用 animalSound() 方法:

示例:

class Program 
{static void Main(string[] args) {Animal myAnimal = new Animal();  // 创建一个 Animal 对象Animal myPig = new Pig();  // 创建一个 Pig 对象Animal myDog = new Dog();  // 创建一个 Dog 对象myAnimal.animalSound();myPig.animalSound();myDog.animalSound();}
}

输出将为:

动物发出声音
猪说:wee wee
狗说

C# 抽象

抽象类和方法

数据抽象是隐藏某些细节并仅向用户显示基本信息的过程。

抽象可以通过抽象类或接口来实现。

abstract 关键字用于类和方法:

  • 抽象类:是一个受限制的类,不能用于创建对象(要访问它,必须从另一个类继承)。
  • 抽象方法:只能在抽象类中使用,并且没有方法体。方法体由派生类(继承自)提供。

抽象类可以同时包含抽象方法和常规方法:

abstract class Animal {public abstract void animalSound();public void sleep() {Console.WriteLine("Zzz");}
}

从上面的例子可以看出,无法创建 Animal 类的对象:

Animal myObj = new Animal(); // 将生成错误(无法创建抽象类或接口“Animal”的实例)

要访问抽象类,必须从另一个类继承它

例子

// 抽象类
abstract class Animal {// 抽象方法(没有方法体)public abstract void animalSound();// 常规方法public void sleep() {Console.WriteLine("Zzz");}
}// 派生类(继承自 Animal)
class Pig : Animal {public override void animalSound() {// animalSound() 的方法体在这里提供Console.WriteLine("The pig says: wee wee");}
}class Program {static void Main(string[] args) {Pig myPig = new Pig(); // 创建一个 Pig 对象myPig.animalSound(); // 调用抽象方法myPig.sleep(); // 调用常规方法}
}

为什么以及何时使用抽象类和方法?

  • 为了实现安全性——隐藏某些细节,只显示对象的重要细节。
  • 注意:抽象也可以通过接口实现

C# Interface

接口是在 C# 中实现抽象的另一种方式。

接口是一个完全“抽象类”,它只能包含抽象方法和属性(没有实际的方法体):

// 接口
interface Animal 
{void animalSound(); // 接口方法(没有方法体)void run(); // 接口方法(没有方法体)
}

通常,以字母 “I” 开头是一种良好的实践,因为这样可以更容易地记住它是一个接口而不是一个类。

默认情况下,接口的成员是抽象和公共的。

注意:接口可以包含属性和方法,但不能包含字段。

要访问接口方法,接口必须由另一个类“实现”(有点像继承)。要实现接口,请使用冒号符号(与继承一样)。接口方法的实际方法体由“实现”类提供。请注意,在实现接口时,不必使用 override 关键字:

// 接口
interface IAnimal 
{void animalSound(); // 接口方法(没有方法体)
}// Pig “实现”了 IAnimal 接口
class Pig : IAnimal 
{public void animalSound() {// animalSound() 的方法体在这里提供Console.WriteLine("猪说:呜呜");}
}class Program 
{static void Main(string[] args) {Pig myPig = new Pig();  // 创建一个 Pig 对象myPig.animalSound();}
} 

接口的注意事项:

  • 与抽象类一样,接口不能用于创建对象(在上面的示例中,在 Program 类中不能创建“IAnimal”对象)。
  • 接口方法没有方法体 - 方法体由“实现”类提供。
  • 在实现接口时,必须覆盖其所有方法。
  • 接口可以包含属性和方法,但不能包含字段/变量。
  • 接口成员默认是抽象和公共的。
  • 接口不能包含构造函数(因为它不能用于创建对象)。

为什么以及何时使用接口?

  1. 为了实现安全性 - 隐藏对象的某些细节,仅显示重要的细节(接口)。
  2. C# 不支持“多继承”(一个类只能继承一个基类)。但是,可以通过接口实现多继承,因为类可以实现多个接口。注意:要实现多个接口,请使用逗号分隔它们(见下面的示例)。

为什么以及何时使用抽象类和方法?

  • 为了实现安全性——隐藏某些细节,只显示对象的重要细节。
  • 注意:抽象也可以通过接口实现

C# 接口

接口是在 C# 中实现抽象的另一种方式。

接口是一个完全“抽象类”,它只能包含抽象方法和属性(没有实际的方法体):

// 接口
interface Animal 
{void animalSound(); // 接口方法(没有方法体)void run(); // 接口方法(没有方法体)
}

通常,以字母 “I” 开头是一种良好的实践,因为这样可以更容易地记住它是一个接口而不是一个类。

默认情况下,接口的成员是抽象和公共的。

注意:接口可以包含属性和方法,但不能包含字段。

要访问接口方法,接口必须由另一个类“实现”(有点像继承)。要实现接口,请使用冒号符号(与继承一样)。接口方法的实际方法体由“实现”类提供。请注意,在实现接口时,不必使用 override 关键字:

// 接口
interface IAnimal 
{void animalSound(); // 接口方法(没有方法体)
}// Pig “实现”了 IAnimal 接口
class Pig : IAnimal 
{public void animalSound() {// animalSound() 的方法体在这里提供Console.WriteLine("猪说:呜呜");}
}class Program 
{static void Main(string[] args) {Pig myPig = new Pig();  // 创建一个 Pig 对象myPig.animalSound();}
} 

接口的注意事项:

  • 与抽象类一样,接口不能用于创建对象(在上面的示例中,在 Program 类中不能创建IAnimal对象)。
  • 接口方法没有方法体 - 方法体由“实现”类提供。
  • 在实现接口时,必须覆盖其所有方法。
  • 接口可以包含属性和方法。

C# 多接口

要实现多个接口,请使用逗号分隔它们:

interface IFirstInterface 
{void myMethod(); // 接口方法
}interface ISecondInterface 
{void myOtherMethod(); // 接口方法
}// 实现多个接口
class DemoClass : IFirstInterface, ISecondInterface 
{public void myMethod() {Console.WriteLine("一些文本..");}public void myOtherMethod() {Console.WriteLine("一些其他文本...");}
}class Program 
{static void Main(string[] args) {DemoClass myObj = new DemoClass();myObj.myMethod();myObj.myOtherMethod();}
}

最后

为了方便其他设备和平台的小伙伴观看往期文章:

微信公众号搜索:Let us Coding,关注后即可获取最新文章推送

看完如果觉得有帮助,欢迎 点赞、收藏、关注

相关文章:

C# 继承、多态性、抽象和接口详解:从入门到精通

C# 继承 在 C# 中,可以将字段和方法从一个类继承到另一个类。我们将“继承概念”分为两类: 派生类(子类) - 从另一个类继承的类基类(父类) - 被继承的类 要从一个类继承,使用 : 符号。 在以…...

python在线聊天室(带聊天保存)

python Socket在线聊天室(带聊天保存) 需求功能 1.聊天信息保存功能(服务端会把信息保存到一个txt里面) 2.使用pyqt5框架作为一个可视化界面 3.具备一个服务端和多个客户端的功能 4.具备离线加入黑名单(离线踢出) 5.具备在线加入黑名单(在线加入黑名单被踢出) 6.具备群聊功能…...

jenkins+gitlab实现Android自动打包填坑之旅

一.背景 1.首先你需要知道你想要实现的Android自动打包的Android项目的一些环境配置及需要使用的一些开发版本。 声明:本文 Android项目基于:1.jdk11 2.SDK无要求 3.gradle无要求(同Manven一样为项目自动化构建开源工具) 注&am…...

洛谷B3625迷宫寻路

迷宫寻路 题目描述 机器猫被困在一个矩形迷宫里。 迷宫可以视为一个 n m n\times m nm 矩阵,每个位置要么是空地,要么是墙。机器猫只能从一个空地走到其上、下、左、右的空地。 机器猫初始时位于 ( 1 , 1 ) (1, 1) (1,1) 的位置,问能否…...

GPT-SoVITS 测试

开箱直用版(使用 AutoDL) step1 打开地址 https://www.codewithgpu.com/i/RVC-Boss/GPT-SoVITS/GPT-SoVITS-Official 选择 AutoDL创建实例,选择 3080ti 机器 step2 创建好实例之后,进入命令行,输入命令 echo {}>…...

人工智能:更多有用的 Python 库

目录 前言 推荐 JupyterLab 入门 复杂的矩阵运算 其它人工智能和机器学习的 Python 库 前言 在这篇文章中,我们将了解更多的矩阵操作,同时再介绍几个人工智能 Python 库。 推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂&#x…...

Linux BIO如何下发到HDD?

在Linux操作系统中,当创建一个Block I/O请求(BIO)时,它会被封装成适合硬件交互的数据结构,并通过内核存储子系统传递到对应的硬件控制器上,如SAS(Serial Attached SCSI)HBA&#xff…...

《动手学深度学习(PyTorch版)》笔记4.6

注:书中对代码的讲解并不详细,本文对很多细节做了详细注释。另外,书上的源代码是在Jupyter Notebook上运行的,较为分散,本文将代码集中起来,并加以完善,全部用vscode在python 3.9.18下测试通过。…...

Hadoop-MapReduce-源码跟读-客户端篇

一、源码下载 下面是hadoop官方源码下载地址,我下载的是hadoop-3.2.4,那就一起来看下吧 Index of /dist/hadoop/core 二、从WordCount进入源码 用idea将源码加载进来后,找到org.apache.hadoop.examples.WordCount类(快捷方法&…...

《游戏-03_3D-开发》之—新输入系统人物移动攻击连击

本次修改unity的新输入输出系统。本次修改unity需要重启,请先保存项目, 点击加号起名为MyCtrl, 点击加号设置为一轴的, 继续设置W键, 保存 生成自动脚本, 修改MyPlayer代码: using UnityEngine;…...

滴水逆向三期笔记与作业——02C语言——10 Switch语句反汇编

滴水逆向三期笔记与作业——02C语言——10 Switch语句反汇编 一、Switch语句1、switch语句 是if语句的简写2、break加与不加有什么特点?default语句可以省略吗?3、游戏中的switch语句(示例)4、添加case后面的值,一个一个增加&…...

燃烧的指针(三)

🌈个人主页:小田爱学编程 🔥 系列专栏:c语言从基础到进阶 🏆🏆关注博主,随时获取更多关于c语言的优质内容!🏆🏆 😀欢迎来到小田代码世界~ &#x…...

微服务架构实施攻略:如何选择合适的微服务通信机制?

随着业务的快速发展和系统的日益复杂,传统的单体应用逐渐显露出瓶颈,已无法满足现代软件研发的需求。微服务架构作为一种灵活、可扩展的解决方案,通过将复杂系统拆分为一系列小型服务来提高系统的可伸缩性、灵活性和可维护性。在实施微服务架…...

【jetson笔记】解决vscode远程调试qt.qpa.xcb: could not connect to display报错

配置x11转发 jetson远程安装x11转发 安装Xming Xming下载 安装完成后打开安装目录C:\Program Files (x86)\Xming 用记事本打开X0.hosts文件,添加jetson IP地址 后续IP改变需要重新修改配置文件 localhost 192.168.107.57打开Xlaunch Win菜单搜索Xlaundch打开 一…...

网络安全产品之认识安全隔离网闸

文章目录 一、什么是安全隔离网闸二、安全隔离网闸的主要功能三、安全隔离网闸的工作原理四、安全隔离网闸的分类五、安全隔离网闸与防火墙的区别四、安全隔离网闸的应用场景 随着互联网的发展,网络攻击和病毒传播的方式越来越复杂,对网络安全的要求也越…...

Java通过模板替换实现excel的传参填写

以模板为例子 将上面$转义的内容替换即可 package com.gxuwz.zjh.util;import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.*; import java.util.HashMap; import java.util.Map; import java.io.IOException; impor…...

眼底增强型疾病感知蒸馏模型 FDDM:无需配对,fundus 指导 OCT 分类

眼底增强型疾病感知蒸馏模型 FDDM:fundus 指导 OCT 分类 核心思想设计思路训练和推理 效果总结子问题: 疾病特定特征的提取与蒸馏子问题: 类间关系的理解与建模 核心思想 论文:https://arxiv.org/pdf/2308.00291.pdf 代码:https://github.c…...

代码随想录算法刷题训练营day17

代码随想录算法刷题训练营day17:LeetCode(110)平衡二叉树 LeetCode(110)平衡二叉树 题目 代码 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(…...

Java集合如何选择

为什么使用集合 当需要存储一组类型相同的数据时,数组是最常用且最基本的容器之一。但是,使用数组存储对象存在一些不足之处,因为在实际开发中,存储的数据类型多种多样且数量不确定。这时,Java 集合就派上用场了。与数…...

简单介绍----微服务和Spring Cloud

微服务和SpringCloud 1.什么是微服务? 微服务是将一个大型的、单一的应用程序拆分成多个小型服务,每个服务负责实现特定的业务功能,并且可以通过网络通信与其他服务通信。微服务的优点是开发更灵活(不同的微服务可以使用不同的开…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

C++使用 new 来创建动态数组

问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...

【C++进阶篇】智能指针

C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...