C#---23:Virtual、abstract、Interface的区别 混合使用的案例

文章目录

      • 1. virtual & abstract & interface 的区别
        • (1)virtual 修饰的方法
        • (2)abstract修饰的方法
        • (3)interface修饰的方法
      • 2. 一个class继承多个interface 的应用
      • 3. 一个class继承一个class和多个interface
      • 4. abstract作为中间介质(将不同的人以及不同的坦克关联到一起)
      • 5. set & get方法的使用
        • (1)class中的set方法的使用
        • (2)set & get 方法一起使用
      • 6. gunner & driver 作为两个消费者,如何消费只有单一功能(IFireable or IRunable的对象)

1. virtual & abstract & interface 的区别


(1)virtual 修饰的方法
  • virtual 关键字用于声明一个方法可以被其派生类重写(override)。如果一个基类中的方法被标记为 virtual,那么任何继承这个基类的派生类都可以选择覆盖(override)这个方法,提供不同的实现。
  • 如果派生类没有显式地覆盖 virtual 方法,那么默认行为就是调用基类中的实现。
  • virtual 方法必须有具体的实现,也就是说,你不能在声明 virtual 方法时省略方法体。

(2)abstract修饰的方法
  • abstract 关键字用于声明一个类或方法是抽象的。抽象类不能被实例化,只能作为其他类的基类。
  • 抽象方法只声明而不包含任何实现,它必须在派生类中被重写。
  • abstract 方法所在的类也必须被声明为 abstract。
  • 派生类可以选择性地覆盖 abstract 类中的非抽象方法,但是所有抽象方法都必须被实现,除非派生类本身也被声明为 abstract。

(3)interface修饰的方法
  • interface 定义了一组方法、属性、事件和索引器的签名,但不包含任何实现细节。它们可以被多个类实现,从而允许这些类之间进行多态操作。
  • 实现接口的类必须提供接口中声明的所有成员的具体实现。
  • 接口可以被多个类实现,因此提供了多重继承的能力,因为 C# 不支持多重类继承。

总结:
virtual 提供了可选的重写能力,abstract 强制派生类必须实现某些功能,而 interface 则定义了一个完全由实现者填充的合同。


2. 一个class继承多个interface 的应用


step1: 创建2个接口文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


step2: 创建1个普通的class类文件:继承了2个interface
在这里插入图片描述


step3:实例化的tank 可以调用2个接口的方法

在这里插入图片描述


step4:最终效果:
在这里插入图片描述


step5:将实例tank赋值给不同的interface:将tank不同类型的功能进一步区分
在这里插入图片描述

step6:最终可以实现的类似下图的右半部分:
在这里插入图片描述


3. 一个class继承一个class和多个interface

如果Tank这个类还想继续扩展,需要添加一些tank自身属性的内容,就需要再多一些继承了


step1: 新建Myobjct类,设置属性的初始值:
在这里插入图片描述

step2: 初始化值的tank的时候,可以为tank赋值:
在这里插入图片描述


4. abstract作为中间介质(将不同的人以及不同的坦克关联到一起)


在这里插入图片描述

step1:新建项目TankProject,并新建Driver与Gunner类:

Driver 类仅仅负责driver相关的内容,具体是开什么车他都会开,就将IRunable对象传递进来即可(实例化的IRunable对象会定义具体的方法)

在这里插入图片描述

在这里插入图片描述


step2:Tank.cs文件的具体内容:


namespace Helloworld.AbstractStudy
{// Tank 类仅做为abstract类,不具体定义,只负责定义哪些方法是必须要重写的internal abstract class Tank : IFireable, IRunable{abstract public void Fire();abstract public void FireAll();abstract public void Run();}// 继承了Tank类,但因为Tank继承了2个interface,所以需要将这2个interface的所有方法重写一遍class SuperTank: Tank{override public void Fire(){Console.WriteLine("SuperTank fire");}override public void FireAll(){Console.WriteLine("SuperTank fire all");}override public void Run(){Console.WriteLine("SuperTank run ...");}}class HeavyTank : Tank{override public void Fire(){Console.WriteLine("HeavyTank fire");}override public void FireAll(){Console.WriteLine("HeavyTank fire all");}override public void Run(){Console.WriteLine("HeavyTank run ...");}}}

step3:Program.cs文件的具体内容:

/*角色:1.Driver :IRunnable2.Gunner :IFireable3.Tank :3.1 IFireable3.2 IRunnable(SuperTank + HeavyTank ) */using Helloworld.AbstractStudy;namespace TankProject
{class Progress{static void Main(string[] args){Console.WriteLine("Hello, Welcome to my Tank Game!");SuperTank st = new SuperTank();//HeavyTank ht = new HeavyTank();Driver driver = new Driver(st);Gunner gunner = new Gunner(st);gunner.Fire();gunner.FireAll();driver.Drive();}}
}

step4:最终显示效果:
在这里插入图片描述


5. set & get方法的使用

(1)class中的set方法的使用
  • set 方法通常出现在属性(property)的定义中。属性提供了一种封装数据成员的方式,使代码更加清晰和易于维护。
  • set 方法允许外部代码修改属性所代表的数据成员,而 get 方法则允许读取该数据成员的值。
public class Person
{private string _name; // 私有字段,存储名字// 定义一个名为 Name 的属性public string Name{get { return _name; } // 返回名字set { _name = value; } // 设置名字,value 是传递给 set 方法的参数}
}// 使用示例
class Program
{static void Main(string[] args){Person person = new Person();// 调用 set 方法设置 Name 属性person.Name = "John Doe";// 调用 get 方法获取 Name 属性Console.WriteLine(person.Name); // 输出: John Doe}
}

(2)set & get 方法一起使用

namespace TankProject
{internal class MainClass{static void Main(string[] args) {Person person = new Person("alien");Console.WriteLine(person.Name); // 输出: alien// 调用 set 方法设置 Name 属性person.Name = "Alien";// 调用 get 方法获取 Name 属性Console.WriteLine(person.Name); // 输出: Alien}public class Person{private string _name; // 私有字段,存储名字public Person(string name){_name = name;}// 定义一个名为 Name 的属性public string Name{get { return _name; } // 返回名字set { _name = value; } // 设置名字,value 是传递给 set 方法的参数}}}
}

在这里插入图片描述

在这里插入图片描述


6. gunner & driver 作为两个消费者,如何消费只有单一功能(IFireable or IRunable的对象)


step1:创建2个新的类:Car & Rocket , 分别只继承IRunable、IFireable:

在这里插入图片描述

在这里插入图片描述


step2:为Driver & Rocket两个类分别设置set方法,方便修改传递进来的实例属性:
在这里插入图片描述

在这里插入图片描述


step3:为Driver & Rocket两个类分别设置set方法,方便修改传递进来的实例属性:

在这里插入图片描述

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

备份软件维护之NETBACKUP NBU知多少

一、基本介绍 NetBackup (NBU) 是一款企业级的数据备份和恢复软件,‌由Symantec公司开发,‌旨在为异构平台提供全面的数据保护。‌ 它支持从远程办公室到数据中心的各种环境,‌包括UNIX、‌Windows、‌Linux和NetWare等操作系统,…

算法-KMP字符串匹配

题目一 解题思路 KMP算法详解 详解next数组 next[i] 就是使子串 s[0…i] 有最长相等前后缀的前缀的最后一位的下标。 总体来说解next数组和模板串匹配的过程很相似&#xff0c;触类旁通 代码模板 #include<iostream> using namespace std; const int N1e510; char …

JavaScript中bind、apply、call的理解

bind、apply、call是什么&#xff1f; bind、apply、call是Function原型的方法&#xff0c;而在js中所有的函数都是Function的实例&#xff0c;所以&#xff0c;有所有函数都可以使用这三个方法。 bind、apply、call有什么作用&#xff1f; 改变this指向 &#xff0c;这是它们…

单元测试--Junit

Junit是Java的单元测试框架提供了一些注解方便我们进行单元测试 1. 常用注解 常用注解&#xff1a; TestBeforeAll&#xff0c;AfterAllBeforeEach&#xff0c;AfterEach 使用这些注解需要先引入依赖&#xff1a; <dependency><groupId>org.junit.jupiter<…

[IMX6ULL]移植NXP Linux Kernel 5.15

移植NXP Linux Kernel 5.15 2024-7-7 hongxi.zhu 1. 下载NXP Linux Kernel 5.15 仓库[nxp-imx/linux-imx] git clone -b lf-5.15.y https://github.com/nxp-imx/linux-imx.git 2. 编译NXP Linux Kernel 5.15 make ARCHarm CROSS_COMPILEarm-linux-gnueabihf- distclean make…

C++树形结构(1 基础)

目录 一.基础&#xff1a; 1.概念&#xff1a; 2.定义&#xff1a; Ⅰ.树的相关基础术语&#xff1a; Ⅱ.树的层次&#xff1a; 3.树的性质&#xff1a; 二.存储思路&#xff1a; 1.结构体存储&#xff1a; 2.数组存储&#xff1a; 三.树的遍历模板&#xff1a; 四.信…

Mysql-索引结构

一.什么是索引&#xff1f; 索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引 二.无索引的情况 找到…

SpringBoot集成Kaptcha验证码

Hi &#x1f44b;, Im shy 有人见尘埃&#xff0c;有人见星辰 1. 什么是Kaptcha验证码? Kaptcha是一个强大的开源Java验证码生成库,由Google开发。它能够生成高度可配置的图片验证码,主要用于防止自动化程序滥用web应用,提高应用的安全性。 2. Kaptcha的主要特性 Kaptch…

3.3-LSTM的改进

文章目录 1改进点1.1多层化1.2 dropout1.2.1具体概念1.2.2应该插入到LSTM模型的哪里 1.3权重共享 2改进之后的LSTMLM的代码实现2.1初始化2.2前向计算2.3反向传播 3相应的学习代码的实现4总结 1改进点 1.1多层化 加深神经网络的层数往往能够学习更复杂的模式&#xff1b;因此这…

AI学习记录 - 图像识别的基础入门

代码实现&#xff0c;图像识别入门其实非常简单&#xff0c;这里使用的是js&#xff0c;其实就是把二维数组进行公式化处理&#xff0c;处理方式如上图&#xff0c;不同的公式代表的不同的意义&#xff0c;这些意义网上其实非常多&#xff0c;这里就不细讲了。 const getSpecif…

vue-快速入门

Vue 前端体系、前后端分离 1、概述 1.1、简介 Vue (发音为 /vjuː/&#xff0c;类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;可以高效地开发用户界面。…

C语言 之 理解指针(4)

文章目录 1. 字符指针变量2. 数组指针变量2.1 对数组指针变量的理解2.2 数组指针变量的初始化 3. 二维数组传参的本质4. 函数指针变量4.1 函数指针变量的创建4.2 函数指针变量的使用 5. 函数指针数组 1. 字符指针变量 我们在前面使用的主要是整形指针变量&#xff0c;现在要学…

C++入门基础:C++中的循环语句

循环语句是编程语言中用来重复执行一段代码直到满足特定条件的一种控制结构。它们对于处理需要重复任务的场景非常有用&#xff0c;比如遍历数组、累加数值、重复执行某项操作直到满足条件等。 但是在使用循环语句的时候需要注意下哈&#xff0c;有时候一不小心会构成死循环或者…

服务器利用宝塔面板部署Django项目

目录 1. 使用命令启动Django项目1.1 使用 Xshell 连接服务器1.2 安装Anaconda1.3 启动Django项目1.4 使用tmux实现项目的后台运行 2. 使用Python项目管理器部署项目2.1 安装宝塔面板和软件2.2 添加站点2.3 上传项目文件2.3.1 收集静态文件2.3.2 生成依赖文件 2.4 安装安装Pytho…

【笔记】学习记录

2024年7月23日 1.图的5中存储方式 2.二叉树的先序&#xff0c;中序&#xff0c;后序遍历。 学了图的存储方式之后&#xff0c;二叉树好像就是小菜一碟一样。注意一下名词的顺序就可以了。 所谓先中后序&#xff0c;就是先根&#xff0c;中根&#xff0c;后根的差别。没有其…

FoundationDB 基本使用

目录 一、FoundationDB介绍 二、安装单机版FoundationDB 2.1 下载安装程序 2.2 安装FoundationDB 2.3 修改配置信息 2.4 管理FoundationDB服务 三、fdbcli的常用命令 3.1连接数据库 3.2退出fdbcli 3.3查看版本 3.4 写模式 3.5写入键值 3.6读取键值 3.7删除键值 …

学习笔记之JAVA篇(0724)

p 方法 方法声明格式&#xff1a; [修饰符1 修饰符2 ...] 返回值类型 方法名&#xff08;形式参数列表&#xff09;{ java语句;......; } 方法调用方式 普通方法对象.方法名&#xff08;实参列表&#xff09;静态方法类名.方法名&#xff08;实参列表&#xff09; 方法的详…

Java之泛型基础

泛型 1 问题引入 在前面学习集合时&#xff0c;我们都知道集合中是可以存放任意对象的&#xff0c;只要把对象存储集合后&#xff0c;那么这时他们都会被提升成Object类型。当我们在取出每一个对象&#xff0c;并且进行相应的操作&#xff0c;这时必须采用类型转换。 观察下…

视频去水印免费电脑版 pdf压缩在线免费网页版 pdf压缩在线免费 简单工具软件详细方法步骤分享

消除视频中的恼人水印&#xff0c;是许多视频编辑爱好者的常见需求。在这篇文章中&#xff0c;我们将探讨几种视频去水印的技巧&#xff0c;在数字化时代&#xff0c;视频和图片的传播越来越方便&#xff0c;但随之而来的水印问题也让人头疼。本文将为您详细介绍视频剪辑去水印…

vue环境安装

安装node.js 网址&#xff1a;https://nodejs.org/en/download/ 直接点击下载就ok 一路next&#xff0c;这里可以改一下保存路径 选第一个 安装后&#xff0c;找到node.js的安装目录&#xff0c;创建这两个文件夹 之后打开命令提示符&#xff0c;右键以管理员身份运行 将新创…