C# 继承

C# 继承

  • 继承的类型
  • 实现继承
  • 虚方法
  • 隐藏方法
  • 调用函数的基类版本
  • 抽象类和抽象函数
  • 密封类和密封方法
  • 派生类的构造函数
  • 修饰符
    • 访问修饰符
    • 其他修饰符
  • 接口

继承的类型

  • 实现继承
    表示一个类型派生于一个基类型,拥有该基类型的所有成员字段和函数。在实现继承中,派生类型的每个函数采用基类型的实现代码,除非在派生类型的定义中指定重写该函数的实现代码。
  • 接口继承
    表示一个类型只继承了函数的签名,没有继承任何实现代码。在需要指定该类型具
    有某些可用的特性时,最好使用这种类型的继承。
  • 多重继承
    一些语言如 C++支持所谓的"多重继承",即一个类派生于多个类。
  • 结构和类
    结构(值类型)和类(引用类型)。使用结构的一个限制是结构不支持继承,但每个结构都自动派生于 System.ValueType。实际上还应更仔细一些:不能建立结构的类型层次,但结构可以实现接口。换言之,结构并不支持实现继承,但支持接口继承。事实上,定义结构和类可以总结为:
    • 结构总是派生于 System.ValueType,它们还可以派生于任意多个接口。
    • 类总是派生于用户选择的另一个类,它们还可以派生于任意多个接口。

实现继承

声明一个类派生于另一个类,可以使用下面的语法:

class MyClass : MyBaseClass
{// 函数和数据成员
}

声明一个类继承其他类和接口

class MyClass : MyBaseClass, IMyInterface1, IMyInterface2
{// 函数和数据成员
}

声明一个结构继承其他接口

struct MyStruct : IMyInterface1, IMyInterface2
{// ...
}

虚方法

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

class MyBaseClass
{public virtual string VirtualMethod(){return "base method:VirtualMethod";}
}

把一个属性声明为virtual,对于虚属性或重写属性,语法与非虚属性是相同的,但要在定义中
加上关键字 virtual,其语法如下所示

public virtual string ForeName
{private string foreName;get { return foreName;}set { foreName = value;}
}

C#中虚函数的概念与标准 OOP 概念相同:可以在派生类中重写虚函数。在调用方法时,会调用对象类型的合适方法。在 C#中,函数在默认情况下不是虚拟的,但(除了构造函数以外)可以显式地声明为 virtual。

class MyClass : MyBaseClass
{public override string VirtualMethod(){return "override method:VirtualMethod";}
}

隐藏方法

如果签名相同的方法在基类和派生类中都进行了声明,但该方法没有声明为 virtual 和 override,派生类方法就会隐藏基类方法。在大多数情况下,是要重写方法,而不是隐藏方法,因为隐藏方法会存在为给定类的实例调用错误方法的危险。
假定有人编写了类 HisBaseClass:

class HisBaseClass
{
}

某一时刻编写了一个派生类,给 HisBaseClass 添加某个功能,特别是要添加一个目前基类中没有的方法 MyGroovyMethod():

class MyDerivedClass : HisBaseClass
{public int MyGroovyMethod(){return 0;}
}

一年后,基类的编写者决定扩展基类的功能。为了保持一致,他也添加了一个名为MyGroovyMethod()的方法,该方法的名称和签名与前面添加的方法相同,但并不完成相同的工作。在使用基类的新方法编译代码时,程序在应该调用哪个方法上就会有潜在的冲突。这在 C#中完全合法,但因为我们的 MyGroovyMethod()与基类的 MyGroovyMethod()不相关,运行这段代码的结果就可能不是我们希望的结果。C#已经为此设计了一种方式,可以很好地处理这种情况。
首先,系统会发出警告。在 C#中,应使用 new 关键字声明我们要隐藏一个方法,如下所示:

class MyDerivedClass: HisBaseClass
{public new int MyGroovyMethod(){return 0;}
}

调用函数的基类版本

C#有一种特殊的语法用于从派生类中调用方法的基类版本:base.< MethodName >()。

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

抽象类和抽象函数

C#允许把类和函数声明为 abstract,抽象类不能实例化,而抽象函数没有执行代码,必须在非抽
象的派生类中重写。显然,抽象函数也是虚拟的(但也不需要提供 virtual 关键字,实际上,如果提供了该关键字,就会产生一个语法错误)。如果类包含抽象函数,该类将也是抽象的,也必须声明为抽象的:

abstract class Building	// 抽象类
{private bool damaged = false; // 成员字段初始值public abstract decimal CalculateHeatingCost(); // 抽象方法
}

密封类和密封方法

C#允许把类和方法声明为 sealed。对于类来说,这表示不能继承该类;对于方法来说,这表示不能重写该方法。sealed 与java中的final相同。

sealed class FinalClass
{//....
}
FinalClass 类不能被其他类继承class MyClass
{public sealed void FinalMethod(){}
}
FinalMethod不能再MyClass的派生类中重写。

派生类的构造函数

  1. 在层次结构中添加无参数的构造函数
public abstract class GenericCustomer
{private string name;public GenericCustomer():base() // 使用base表示这是基类构造函数{name = "< no name >";}}
  1. 在层次结构中添加带参数的构造函数
abstract class GenericCutomer
{private string name;public GenericCutomer(string name){this.name = name;}
}
class Nevermore60Customer : GenericCutomer
{public Nevermore60Customer(string name, string referrerName):base(name){this.referrerName = referrerName;}private string referrerName;private uint highCostMinutesUesd;
}

修饰符

访问修饰符

在这里插入图片描述

其他修饰符

在这里插入图片描述

接口

接口有interface声明

public interface IDisposable
{void Dispose();
}

类派生接口

class SomeClass:IDisposable
{public void Dispose(){// 实现接口方法}
}

接口的定义

namespace Wrox.ProCSharp
{public interface IBankAccount{void PlayIn(decimal amount);bool Withdraw(decimal amount);decimal Balance{get;}}}

接口的继承

namespace Wrox.ProCSharp.VenusBank
{public class SaverAccount : IBankAccount{private decimal balance;public void PayIn(decimal amount){balance += amount;	}public bool Withdraw(decimal amount){if (balance >= amount){balance -= amount;return true;}Console.WriteLine("error.");return false;}public decimal Balance{get {return balance;	}}public override string ToString(){return String.Format("Vens Bank Saver: Balance = {0,6:C}", balance);}}}

不同类实现相同的接口

namespace Wrox.ProCSharp.JupiterBank 
{public class GoldAccount:IBankAccount{// ...}
}

测试代码

using System;
using Wrox.ProCSharp;
using Wrox.ProCSharp.VenusBank;
using Wrox.ProCSharp.JupiterBank;namespace Wrox.ProCSharp
{class MainEntryPoint{static void Main(string[] args){IBankAccount venusAccount = new SaverAccount();IBankAccount jupiterAccount = new GoldAccount();venusAccount.PayIn(200);venusAccount.Withdraw(100);Console.WriteLine(venusAccount.ToString());jupiterAccount.PayIn(500);jupiterAccount.Withdraw(600);jupiterAccount.Withdraw(100);Console.WriteLine(jupiterAccount.ToString());}}
}

接口数组

IBankAccount[] accounts = new IBankAccount[2];accounts[0] = new SaverAccount();
accounts[1] = new GoldAccount();

派生接口
接口可以彼此继承,其方式与类的继承相同。

namespace Wrox.ProCSharp
{public interface ITransferBankAccount: IBankAccount{bool TransferTo(IBankAccount desination, decimal amount);}
}

派生接口类

public class CurrentAccount : ITransferBankAccount
{private decimal balance;public void PayIn(decimal amount){balance += amount;}public bool Withdraw(decimal amount){if (balance >= amount){balance -= amount;return true;}Console.WriteLine("Withdrawal failed.");return false;}public decimal Balance{get { return balance;}}public bool TransferTo(IBankAccount destination, decimal amount){bool result;if ((result = Withdraw(amount)) == true){destination.PayIn(amount);return result;}}public override string ToString(){return String.Format("Jupiter Bank Current Account:Balance = {0, 6:C}", balance);}
}// 验证代码static void Main()
{IBankAccount venusAccount = new SaverAccount();ITransferBankAccount jupiterAccount = new CurrentAccount();venusAccount.PayIn(200);jupiterAccount.PayIn(500);jupiterAccount.TransferTo(venusAccount, 100);Console.WriteLine(venusAccount.ToString());Console.WriteLine(jupiterAccount.ToString());
}

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

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

相关文章

Seata入门系列【1】安装seata 1.7.1+nacos 2.1.1

1 介绍 Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案。 Github: https://github.com/seata/seata 官方文档&#xff1a;h…

苹果曾考虑基于定位控制AirPods Pro自适应音频

在一次最近的采访中&#xff0c;苹果公司的高管Ron Huang和Eric Treski透露&#xff0c;他们在开发AirPods Pro自适应音频功能时&#xff0c;曾考虑使用GPS信号来控制音频级别。这个有趣的细节打破了我们对AirPods Pro的固有认知&#xff0c;让我们对苹果的创新思维有了更深的…

Anaconda启动错误

错误 An unexpected error occurred on Navigator start-up | Could not find a suitable TLS CA certificate bundle, invalid path 导致Anaconda启动失败&#xff01; [解决办法]1 找到anaconda的安装目录&#xff0c;该目录下的__init__.py 这两处分别改为verifyself.sessio…

Qt Charts简介

文章目录 一.图标类型Charts分类1.折线图和样条曲线图2.面积图和散点图3.条形图4.饼图5.误差棒图6.烛台图7.极坐标图 二.坐标轴Axes类型分类三.图例四.图表的互动五.图表样式主题 一.图标类型Charts分类 图表是通过使用系列类的实例并将其添加到QChart或ChartView实例来创建的…

每日一练 | 华为认证真题练习Day115

1、FEC(Forwarding Equivalence Class)转发等价类&#xff0c;是一组具有某些共性的数据流的集合&#xff1b;FEC可以根据地址进行划分&#xff0c;但是不能根据业务类型、QoS等要素进行划分。 A. 对 B. 错 2、关于OSI参考模型中网络层的功能说法正确的是&#xff1f; A. OS…

26069-2022 硅单晶退火片 思维导图

声明 本文是学习GB-T 26069-2022 硅单晶退火片. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本文件规定了硅单晶退火片(以下简称退火片)的分类、技术要求、试验方法、检验规则、包装、标志、 运输、贮存、随行文件及订货单内容。 本文件…

VUE的基本使用——hello,vue

一、准备一个容器root 二、创建一个Vue实例 三、配置容器 四、配置数据 五、将数据渲染到容器中 总结 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthde…

实现数据库用户校验

导入my-batis-plus依赖&#xff1a; <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> </depende…

c++堆排序-建堆-插入-删除-排序

本文以大根堆为例&#xff0c;用数组实现&#xff0c;它的nums[0]是数组最大值。 时间复杂度分析&#xff1a; 建堆o(n) 插入删除o(logn) 堆排序O(nlogn) 首先上代码 #include<bits/stdc.h>using namespace std; void down(vector<int>&nums, int idx, i…

SpringMVC 学习(七)JSON

9. JSON 9.1 简介 JSON&#xff08;JavaScript Object Notation&#xff0c;JS 对象标记&#xff09;是一种轻量级数据交换格式&#xff0c;采用独立于编程语言的文本格式储存和表示数据&#xff0c;易于机器解析和生成&#xff0c;提升网络传输效率。 任何 JavaScript 支持…

Midjourney 生成油画技巧

基本 prompt oil painting, a cute corgi dog surrounded with colorful flowers技法 Pointillism 点描绘法 笔刷比较细&#xff0c;图像更精细 oil painting, a cute corgi dog surrounded with colorful flowers, pontillismImpasto 厚涂绘法 笔刷比较粗&#xff0c;图像…

将切分的图片筛选出有缺陷的

将切分的图片筛选出有缺陷的 需求代码 需求 由于之前切分的图像有一些存在没有缺陷&#xff0c;需要再次筛选 将可视化的图像更改后缀 更改为xml的 可视化代码 可视化后只有7000多个图像 原本的图像有1W多张 代码 # 按照xml文件删除对应的图片 # coding: utf-8 from P…

unittest单元测试框架使用

什么是unittest 这里我们将要用的unittest是python的单元测试框架&#xff0c;它的官网是 25.3. unittest — Unit testing framework — Python 2.7.18 documentation&#xff0c;在这里我们可以得到全面的信息。 当我们写的用例越来越多时&#xff0c;我们就需要考虑用例编写…

Redis实现Session持久化

Redis实现Session持久化 1. 前言 直接使用Session存储用户登录信息&#xff0c;此时的会话信息是存储在内中的&#xff0c;只要项目重启存储的Session信息就会丢失。而使用Redis存储Session的话就不会存在这种情况&#xff0c;即使项目重启也并不影响&#xff0c;也无需用户重…

GIT提示Another git process seems to be running in this repository

解决方法 1、进入项目里面的.git文件里面找到index.lock删除即可。

掷骰子的多线程应用程序2基于互斥量的线程同步(复现《Qt C++6.0》)

说明&#xff1a;在复现过程中出现两点问题&#xff08;1&#xff09;run()函数中对m_diceValued的赋值&#xff08;2&#xff09;do_timeOut()函数中没有对m_seq、m_diceValued进行定义。修改后的复现程序如下所示&#xff1a; 主线程&#xff1a; .h #pragma once#include…

PostgreSQL 查询某个属性相同内容出现的次数

查询某个数据库表属性 name 相同内容出现出现的次数&#xff0c;并按次数从大到小排序 SELECT name, COUNT(*) AS count FROM your_table GROUP BY name ORDER BY count DESC;示例 select project_id, COUNT(*) AS count from app_ads_positions group by project_id order b…

mysql Your password does not satisfy the current policy requirements

在修改密码时遇到 Your password does not satisfy the current policy requirements 原因&#xff1a;您的密码不符合当前策略要求&#xff0c;最好是把密码设置成复杂的&#xff0c;包括字母大小写、数字、特殊字符。 如果你还是先把数据库密码改简单&#xff0c;比如你本地…

vue点击按钮收缩菜单

问题描述 VUE菜单有一个BUG&#xff0c;当我们点击其它按钮或者首页的时候&#xff0c;已经展示的一级菜单是不会自动收缩的。这个问题也导致很多开发者把一级菜单都换成了二级菜单。 错误展示 错误的效果请看下图。 解决方法 1、寻找菜单文件 因为我使用的是ruoyi的前端框…

Spring Controller内存马

获取当前上下文运行环境 getCurrentWebApplicationContext WebApplicationContext context ContextLoader.getCurrentWebApplicationContext(); 在SpringMVC环境下获取到的是一个XmlWebApplicationContext类型的Root WebApplicationContext&#xff1a; 在Spring MVC环境中…