C#-抽象类与接口

news2024/11/17 22:35:12

文章目录

  • 一、抽象类和接口总结
    • 总结
    • 补充说明
    • 主要区别
  • 二、抽象类
    • 2.1 抽象类概述与声明
    • 2.2 抽象方法
    • 2.3 抽象类与抽象方法的使用
  • 三、接口
    • 3.1 接口概述
      • 概述
      • 特征
      • 声明
      • 示例
    • 3.2 接口的实现和继承
      • 说明
      • 示例
    • 3.3 显式接口成员实现
      • 说明
      • 注意
      • 示例

一、抽象类和接口总结

总结

抽象类和接口这两种类型用于完全不同的目的。抽象类主要用作对象的基类,贡献某些主要的特性,例如共同的目的和结构。
接口则主要是用于类,为这些类去添加不同的方法(行为)。

补充说明

抽象类和接口都包含可以由派生类继承的成员,他们都能直接实例化,但可以声明他们的变量;
这样做,可以使用多态性把继承这两种类型的对象指定给他们的变量;
接着通过这些变量来使用这些类型的成员,但不能直接访问派生类中的其他成员【如上述例子】

主要区别

1、他们的派生类只能继承一个基类,即只能直接继承一个抽象类,但可以继承任意多个接口;
2、抽象类中可以定义成员的实现,但接口中不可以;
3、抽象类中可以包含字段、构造函数、析构函数、静态成员或常量等,接口中不可以;
4、抽象类中的成员可以是私有的(只要他们不是抽象的)、受保护的、内部的或受保护的内部成员(受保护的内部成员只能在应用程序的代码或派生类中访问),但接口中的成员必须是公共的。

二、抽象类

2.1 抽象类概述与声明

一般将父类定义为抽象类,需要使用这个父类进行多态与继承。
继承树中越是向上,类就越发抽象;例如:奔驰继承汽车类,汽车类继承交通工具类等。

声明:使用abstract关键字

访问修饰符  abstract class 类名:基类或接口
{
}

声明抽象类

public abstract class myClass
{
	public int i;
	public void func()
	{	}
}

声明抽象类时,abstract、class和类名外是必须的;其余可选

2.2 抽象方法

抽象方法没有方法体,这个方法本身没有任何意义,需要被继承的类进行重写。
如果一个类中有抽象方法,那么这个类就需要被标记为抽象类。

抽象方法必须声明在抽象类中。
声明抽象方法时,不能使用virtual、static、private修饰符。

抽象方法声明引入了一个新方法,不提供方法的实现,因此方法体只包含一个分号。
当从抽象类的派生一个非抽象类时,需要在非抽象类中重写抽象方法,以提供具体的实现,重写抽象方法时使用override关键字。

声明:使用使用abstract关键字

public abstract class myClass
{
	public int i;
	public void func()
	{	}
	//声明抽象方法
	public abstract void method();
}

2.3 抽象类与抽象方法的使用

//声明抽象类
    abstract class MyClass
    {
        private string name;
        private int age;
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        public int Age
        {
            get { return age; }
            set { age = value; }
        }
        //抽象方法
        public abstract void showInfo();
    }
    //继承抽象类
    class SonClass : MyClass
    {
    //重写抽象方法
        public override void showInfo()
        {
            Console.WriteLine($"My name is:{this.Name},I am {this.Age} years old.");
        }
    }
    internal class Program
    {
        static void Main(string[] args)
        {
            SonClass sonClass = new SonClass();	//实例化派生类
            MyClass son = sonClass;	//使用派生类实例化抽象类
            son.Age = 10;
            son.Name = "Nick";
            son.showInfo();
            Console.ReadLine();
        }
    }

运行结果:
运行结果

三、接口

3.1 接口概述

概述

由于C#中是单继承,但客观世界中出现多重继承的情况比较多,因此通过接口实现多重继承的功能。
接口是抽象类的延申,可以视作纯粹的抽象类,其中的所有方法都没有方法体。
使用接口继承关系
接口用来定义程序的协议,描述可属于任何类或结构的一组相关行为。
接口可由 方法、属性、事件、索引器 4种成员类型的任何组合构成,但不能包含字段。
类和结构可以继承多个接口,接口也可以继承其他的接口。

特征

接口可以将方法、属性、索引器、事件作为成员,但不能给这些成员设置具体的值。
特征:
类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。
不能直接实例化接口。
接口可以包含事件、索引器、方法和属性。
接口不包含方法的实现。
类和结构可从多个接口继承。
接口自身可从多个接口继承。

声明

使用interface关键字,语法格式如下:

修饰符		interface		接口名称:继承的接口列表
{
	接口内容;
}

声明接口时,除interface关键字和接口名称外,其他的都是可选项;
可使用new、public、protected、internal、private等修饰符声明接口,但接口成员必须是公开的。

示例

interface ImyInterface
{
	string ID		//编号(可读可写)
	{
		get;
		set;
	}
	string Name		//姓名(可读可写)
	{
		get;
		set;
	}
	void ShowInfo();		//显式定义的编号和姓名
}

3.2 接口的实现和继承

说明

实现接口成员,类中对应的成员必须是公共的、非静态的,并且与接口成员具有相同的名称和签名。
类的属性和索引器可以为接口上定义的属性或索引器定义额外的访问器;例如,接口定义一个带有get的访问器属性,而实现该接口的类,可以声明同时带有get和set访问器的同意属性;但是,如果属性或索引器使用 显示 实现,则访问器必须匹配。

接口的实现通过类继承实现。声明实现接口的类时,需要在基类列表中包含所实现的接口的名称。

示例

    interface ITest1
    {
        void Test1();
    }
    interface ITest2:ITest1
    {
        void Test2();
    }
    class TestClass :  ITest2
    {
        public void Test1()
        {
            Console.WriteLine("ITest1接口的Test1()方法");
        }

        public void Test2()
        {
           Console.WriteLine("ITest2接口的Test2()方法");
        }
    }

3.3 显式接口成员实现

说明

如果类实现两个接口,并且两个接口包含具有相同签名的成员,那么在类中实现该成员将导致两个接口都使用该成员作为他们的实现。
这样可能会导致接口实现的不正确,因此需要显示实现接口成员,即创建一个仅通过该接口调用并且特定于该接口的类成员。
显示接口实现是通过 使用 接口名称和一个句点 命名该类成员来进行实现。

注意

显示接口成员实现中 不能包含 访问修饰符、abstract、virtual、override或static修饰符。
显示接口成员属于接口的成员,而不是类的成员你,因此,不能使用类对象直接访问,只能通过接口对象来访问。

示例

    interface ImyInterface1
    {
        int Add();
    }
    interface ImyInterface2
    {
        int Add();
    }
    class My_Class : ImyInterface1, ImyInterface2
    {
        int ImyInterface2.Add() { return 1; }
        int ImyInterface1.Add() { return 0; }
    }
    internal class Program
    {
        static void Main(string[] args)
        {
                My_Class myClass = new My_Class();
                //myClass对象中不包含Add方法,只能通过实例化接口对象来调用Add方法
                ImyInterface1 imyInterface1 = myClass;
                Console.WriteLine($"调用接口ImyInterface1 中的Add方法结果为: {imyInterface1.Add()}");

                //将myClass作为ImyInterface2,来调用其中的Add()方法
                Console.WriteLine($"调用接口ImyInterface2 中的Add方法结果为: {(myClass as ImyInterface2).Add()}");
                Console.ReadLine();
        }
    }

运行结果:
运行结果

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

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

相关文章

k8s使用ECK(2.4)形式部署elasticsearch+kibana-http协议

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、准备elasticsearch-cluster.yaml二、部署并测试总结 前言 之前写了eck2.4部署eskibana,默认的话是https协议的,这里写一个使用http…

【docker】docker的一些常用命令-------从小白到大神之路之学习运维第92天

目录 一、安装docker-ce 1、从阿里云下载docker-cer.epo源 2、下载部分依赖 3、安装docker 二、启用docker 1、启动docker和不启动查看docker version 2、启动服务查看docker version 有什么区别?看到了吗? 3、看看docker启动后的镜像仓库都有什…

解密Spring MVC异常处理:从局部到全局,打造稳固系统的关键步骤

😀前言 在现代软件开发中,异常处理是不可或缺的一部分,它能够有效地提高系统的稳定性和健壮性。在Spring MVC框架中,异常处理机制起着至关重要的作用,它允许开发者在程序运行过程中捕获、处理和报告异常,从…

26 Linux高级篇-Linux面试题

26 Linux高级篇-Linux面试题 文章目录 26 Linux高级篇-Linux面试题1.分析日志t.txt(访问量),将各个ip地址截取,并统计出现次数,并按从大到小排序(腾讯)2.统计连接到服务器的各个ip情况,并按连接数从大到小排序(腾讯)3.如忘记了mys…

历时3天的springboot+vue打包成jar包

有人说问什么打包花了三天,里面的坑很多,我就先不叙述太多,直接说我搞了三天得出来的最后解决方案,不一定适合每一个人!! # 前端 # 修改prod.env.js文件下的内容,把里面的 BASE_API 修改为和dev.env.js文件…

[管理与领导-63]:IT基层管理者 - 潜技能 - 1 - 职场中的陷阱 - 看清楚职场中的霸凌现象

目录 前言: 1:打击自尊心 2:孤立他人 3:恶意针对 4:当众羞辱 5:持续性否定 前言: 职场中,什么样的人都有。 害人之心不可有,防人之心不可无。 前者教人从善&…

顺序栈(数组形式)的实现

🌈什么是栈? 1.抽象化具象:可以理解为一个细长的乒乓球筒,一端封闭,放球只能从另一端放入球,取出球时也只能从该端取出。先进的球最后出,后进的球最先出。 2.定义:栈是一种线性数据…

【C++】map/multimap容器

1.map基本概念 2.map构造和赋值 #include <iostream> using namespace std;//map容器 构造和赋值 #include<map>//遍历输出map容器 void printMap(const map<int, int>& m) {for (map<int, int>::const_iterator it m.begin(); it ! m.end(); it)…

Ubuntu学习---跟着绍发学linux课程记录(第一部分)

文章目录 1、启动、关闭、挂起、恢复&#xff08;电源&#xff09;2、更多虚拟机操作2.1 电源设置2.2 硬件参数设置2.3 状态栏2.4 全屏显示 3、快照与系统恢复4、桌面环境5、文件系统6、用户目录7、创建目录和文件8、命令行&#xff1a;文件列表ls 9、命令行&#xff1a;切换目…

分布式任务调度框架

分布式任务调度框架 学习为主 文章目录 分布式任务调度框架一、概念二、架构图三、任务调度的流程定时触发任务是如何实现的&#xff1f;&#xff1a;使用时间轮实现定时执行任务逻辑:3.1 对到达now时间后的任务&#xff08;超出now 5秒外)3.2 对到达now时间后的任务&#xff0…

从代码设计看 Glide 之生命周期(上)

欢迎关注我的其他平台账号&#xff1a; 掘金&#xff1a;0xforee 个人博客&#xff1a;0xforee’s blog 微信公众号&#xff1a; 上期我们探索了一个具备核心功能的图片加载库该怎么设计。这一期我们来看看如何给这个图片加载库关联生命周期管理。 欢迎关注本系列其他文章&…

PPPoE连接无法建立的排查和修复

嗨&#xff0c;亲爱的读者朋友们&#xff01;你是否曾经遇到过PPPoE连接无法建立的问题&#xff1f;今天我将为你详细解析排查和修复这个问题的步骤。 检查物理连接 首先&#xff0c;我们需要确保物理连接没有问题。请按照以下步骤进行检查&#xff1a; - 检查网线是否插好&…

vue训练场练习props和$emit,实现大写输入,小写输出。

场景&#xff1a; 在vue官网训练场&#xff0c;使用训练场中的组件。 仅作为练习笔记&#xff0c;仅供产考。 App.vue 组件代码 方式一&#xff1a;Watch监听 方式二&#xff1a;input绑定

安卓系列机型--软扩容“system分区扩容”操作步骤解析 增加系统分区大小

感兴趣的友友要区别扩容的概念。软扩容与硬扩容。硬扩容指拆解手机字库。更换大容量的字库来达到硬扩容。例如864硬扩容为8256等等。所谓的软扩容指的是将系统默认的系统分区大小修改分区表增大分区。例如原来系统分区默认2G。修改分区表为3G大小。意义在于可以刷写有些需要扩容…

ssm+vue“魅力”繁峙宣传网站源码和论文

ssmvue“魅力”繁峙宣传网站源码和论文102 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身…

CH341 USB总线转接芯片

产品概述&#xff1a; CH341是一个USB总线的转接芯片&#xff0c;通过USB总线提供异步串口、打印口、并口以及常用的2线和4线等同步串行接口。 在异步串口方式下&#xff0c;CH341提供串口发送使能、串口接收就绪等交互式的速率控制信号以及常用的MODEM联络信号&#xff0c;用于…

css transition属性

如果想实现一些效果&#xff1a;比如一个div容器宽高拉伸效果&#xff0c;或者一些好看的有过渡的效果可以使用 定义和用法 transition 属性是一个简写属性&#xff0c;用于设置四个过渡属性&#xff1a; transition-property transition-duration transition-timing-func…

视频动态壁纸 Dynamic Wallpaper for Mac中文

Dynamic Wallpaper是一款Mac平台上的动态壁纸应用程序&#xff0c;它可以根据时间等因素动态切换壁纸&#xff0c;提供更加生动和多样化的桌面体验。 Dynamic Wallpaper包含了多个动态壁纸&#xff0c;用户可以根据自己的喜好选择和切换。这些动态壁纸可以根据时间等因素进行自…

目标检测后的图像上绘制边界框和标签

效果如图所示&#xff0c;有个遗憾就是CV2在图像上显示中文有点难&#xff0c;也不想用别的了&#xff0c;所以改成了英文&#xff0c;代码在下面了&#xff0c;一定要注意一点&#xff0c;就是标注文件的读取一定要根据自己的实际情况改一下&#xff0c;我的所有图像的标注文件…

大数据Flink(七十):SQL 动态表 连续查询

文章目录 SQL 动态表 & 连续查询 一、​​​​​​​SQL 应用于流处理的思路