.net---继承和多态

news2025/8/2 10:06:54

继承和多态

  • 继承和多态的基本概念
    • 继承
    • 继承的类型
      • 实现继承
      • 接口继承
  • 继承
    • 派生类
    • base关键字
    • 构造函数的调用
    • 类成员的继承
    • 类成员的隐藏
    • 继承:虚方法和隐藏方法
  • 抽象类和抽象方法
    • 抽象类
    • 抽象方法
  • 密封类和密封方法
    • 密封类
  • 接口
    • 接口成员
    • 接口实现
  • 多态
    • 重载
    • 重写

继承和多态的基本概念

继承

  • 允许无需重新改写现有类,重用现有类(基类,亦称超类、父类)去创建新类(子类,亦称派生类)

  • C#所有类继承于Object类
    在这里插入图片描述

  • 多态性
    对象可以表示多个类型的能力,以自己的方式响应同一消息

继承的类型

实现继承

  • 一个类型派生于一个基类型,派生类具有基类的所有非私有(非private)数据和行为

  • 派生类型的每个方法采用基类型的实现代码,除非在派生类型的定义中指定重写该方法的实现代码

  • 一般用于增加现有类型的功能,或许多相关的类型共享一组重要的公共功能的场合

接口继承

  • 一个类型实现若干接口,接口仅包含方法的签名,不继承任何实现代码

  • 一般用于指定该类型具有某类可用的特性,在接口中定义通用的实现代码是没有意义的

  • 接口即契约,类型派生于接口,即保证该类提供该接口规定的功能

继承

派生类

[类修饰符] class 类名 [: 基类] {类体;}

  • 在类名称后放置一个冒号,然后在冒号后指定要从中继承的类(即基类)
  • C#的一个派生类只能继承于一个基类
class Point    //等同于:class Point : Object
{
    int x, y;
}
class ColoredPoint : Point  //派生类,从Point派生
{
    int color;
}
class Colored3dPoint : ColoredPoint//派生类,从ColoredPoint派生
{
    int z;
}

base关键字

用于从派生类中访问基类的成员
base(参数):指定创建派生类实例时应调用的基类构造函数
base.方法(参数):调用基类上已被其他方法重写的方法
base.字段名:访问基类的数据成员

不能从静态方法中使用 base 关键字
只能在实例构造函数、实例方法或实例访问器中使用

public class Person 
//等同于:class Person : Object
{ 
    public String name;  public int age;
    public Person(String name, int age) 
//基类构造函数
    { 
        this.name = name;  this.age = age;
    }
    public void print()  //基类的实例方法
    {             
        Console.Write("name={0},age={1}", this.name, this.age);
    }
}
public class Student : Person //派生类
{          
    public String studentID;
    public Student(String name, int age, String id)
        : base(name, age) 
//派生类构造函数,使用base调用基类构造函数
    { 
        this.studentID = id;
    }
    public new void print()
    {
        base.print();          
//使用base调用基类的方法
        Console.WriteLine(",studentID={0}", this.studentID);
    }
}

构造函数的调用

构造函数不能被继承,也不能被覆盖,名称必须与类名相同
通过关键字new创建对象实例时,会根据传入的参数调用相匹配的构造函数
调用构造函数前,需要先调用其基类的构造函数

类成员的继承

通过继承,派生类继承基类中除构造函数之外的所有成员
与基类成员的访问修饰符无关

类成员的隐藏

如果在派生类中声明了与继承的成员同名的成员,则该重名成员将隐藏从基类继承的同名成员变量

class Parent  // 基类Parent
{
    public String name;
    public String sex;
}
class Child : Parent      // 派生类Child
{
    public String name;  
// 成员变量,隐藏从基类继承的同名成员变量name
    public Child(String name, String sex) // 构造函数
    {
        this.name = name;            
//this.name引用Child声明的成员变量
        this.sex = sex;               
//this.sex引用从Parent继承的成员变量
        base.name = name + "'s parent"; 
//base.name引用从基类Parent继承的同名成员变量name
    }
    public void print()
    {
        Console.WriteLine(this.name + " " + this.sex + " " + base.name);
    }
}

继承:虚方法和隐藏方法

  • 虚方法
    在基类中,使用virtual关键字声明的方法

  • 隐藏方法
    在派生类中,使用new关键字声明的与基类中相同签名的方法
    派生类中相同签名方法重新定义了基类中的方法,即隐藏了基类中的同名方法

  • 重写方法
    在派生类中,使用关键字override声明的与基类中相同签名的方法

在这里插入图片描述

  • 基类的虚方法声明用于引入新方法
  • 派生类的重写方法用于使继承的虚方法专用化
  • 虚方法和重写方法主要用于实现多态

抽象类和抽象方法

抽象类

  • 将关键字 abstract 置于关键字 class 的前面可以将类声明为抽象类

  • 抽象类不能实例化(不能用new),一般用于提供多个派生类可共享的基类的公共定义

  • 可以定义抽象类型的变量,但其值必须为 null,或者是其派生的非抽象类的实例的引用

  • 允许(但不要求)抽象类包含抽象成员

  • 抽象类不能被密封

  • 当从抽象类派生非抽象类时,这些非抽象类必须实现所继承的所有抽象成员,从而重写那些抽象成员

抽象方法

抽象类中通过将关键字 abstract 添加到实例方法的返回类型的前面可以定义抽象方法

  • 只允许在抽象类中声明抽象方法
  • 抽象方法同时隐含为虚方法,但不能有virtual修饰符
  • 抽象类的派生类如果是非抽象类,则必须重写抽象基类的所有抽象方法
  • 派生类中,不能用base直接引用抽象基类的抽象方法
 abstract class Animal      
// 基类Animal:抽象类
    {
        public String name;
        public abstract void SayHi();
     public Animal(String name) 
     { this.name = name; }  //构造函数
    }

    class Dog : Animal        // 派生类Dog
    {    //重写SayHi()
public override void SayHi() { Console.WriteLine(this.name + " Wow Wow!"); }
public Dog(String name) : base(name) { }   
//构造函数
    }

    class Cat : Animal        // 派生类Cat
    {  //重写SayHi()
        public override void SayHi() { Console.WriteLine(this.name + " Mew Mew!"); }
        public Cat(String name) : base(name) { }            //构造函数
    }

    //class Horse : Animal { } //编译错误,非抽象类Horse继承了抽象类Animal,但未实现抽象方法
    abstract class Fish : Animal //编译OK,抽象类Fish继承了抽象类Animal,但未实现抽象方法
    {
        public Fish(String name) : base(name) { }
    }

密封类和密封方法

密封类

通过将关键字 sealed 置于关键字 class 的前面,可以将类声明为密封类

  • 不能用作基类,也不能是抽象类
  • 主要用于防止非有意的派生
  • 如果实例方法声明包含sealed 修饰符,则它必须也包含 override 修饰符
  • 把类或方法声明为抽象,表示该类或方法必须被重写或继承;而把类或方法声明为密封,表示该类或方法不能重写或继承

接口

接口定义协定

在这里插入图片描述

  • 接口类似于抽象基类,不能实例化
  • 接口只指定实现该接口的类或结构必须提供的成员,不提供实现
  • 继承接口的任何非抽象类型必须实现接口的所有成员
  • 接口可以包含事件、索引器、方法和属性,但不能包含字段

接口成员

  • 接口成员只能包含方法、属性、索引器和事件的声明
  • 所有接口成员都隐式地具有public访问属性,不能包含任何修饰符

接口实现

接口可由类和结构实现

[类修饰符] class 类名:基接口列表
{
     类体;
}

接口分部与继承

public interface IDimensions  //基类:接口IDimensions
{
    float getLength(); float getWidth();
}
  public class Box : IDimensions    //派生类Box
  {
    float length;  float width;
    Box(float length, float width)
    {
        this.length = length;  this.width = width;
    }
    public float getLength() { return length;}
    public float getWidth() { return width; }
  }

多态

  • 派生类对象可以表示多个类型的能力

  • 类方法多态性的实现有两种方式:方法重载和方法重写

在这里插入图片描述

重载

class P0 // 基类
{ 
    public void MethodA(){Console.WriteLine("调用类P0的方法methodA()");}
}
class C0 : P0 // 派生类
{ 
    public void MethodA(String str1) //重载方法:重载从基类继承的MethodA()
    { 
      Console.WriteLine("调用类C0的方法MethodA():" + str1);
    }
    public void MethodB(String str1) //重载方法:重载MethodB(int a)
    { 
      Console.WriteLine("调用C0类的实例方法MethodB(String str1):" + str1);
    }
    public void MethodB(int a) // 重载方法:重载MethodB(String str1)
    { 
      Console.WriteLine("调用C0类的实例方法MethodB(int a):" + a);
    }
}

重写

class A0 // 基类
{ 
    public virtual void MethodA()
    {
        Console.WriteLine("调用A0的类的实例方法MethodA()");
    }
}
class A01 : A0 // 派生类
{ 
    public override void MethodA()//重写方法:重写从基类A0继承的方法
    {    
        Console.WriteLine("调用A01的类的实例方法MethodA()");
    }
}
class A02 : A0 // 派生类
{
    public override void MethodA()//重写方法:重写从基类A0继承的方法
    {    
        Console.WriteLine("调用A02的类的实例方法MethodA()");
    }
}

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

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

相关文章

NIO中ByteBuffer

// Invariants: mark < position < limit < capacityprivate int mark -1;private int position 0;private int limit;private int capacity; 从源码中可以看出&#xff0c;ByteBuffer的几个实例变量。我们稍后会详细解析这几个变量的意义。 在我们刚创建ByteBuff…

绿色积分消费时代来临,共享购跟随国家的号召

近年来&#xff0c;中国共享经济商业模式不断发展成熟。自2016年国家“十三五”规划纲要首次提出“共享经济”概念以来&#xff0c;中国政府不断助推共享经济发展。最新发布的《共享经济指导原则与基本框架》为共享经济作出定义&#xff1a;共享经济即“资源供给者通过平台与资…

IDEA配置Maven

1. IDEA配置Maven环境 先在IDEA中配置Maven环境&#xff1a; 选择 IDEA中 File --> Settings 搜索 maven 设置 IDEA 使用本地安装的 Maven&#xff0c;并修改配置文件路径 2. IDEA 创建 Maven项目 创建模块 创建模块&#xff0c;选择Maven&#xff0c;点击Next 填写模块名称…

你不知道的Spring的依赖的查找和注入的来源

1.写在前面 前面的博客我们已经介绍完了spring的依赖的查找和注入的方式&#xff0c;这篇博客我们主要介绍下spring的依赖的查找和注入的来源。 2.依赖查找的来源 查找来源 Spring 內建 BeanDefintion Spring 內建单例对象 上面的各种依赖都是在spring的生命周期的过程中&am…

干掉可恶的弹窗广告——windows系统

一、背景 许多国产软件为了生计&#xff0c;内嵌了无数广告。有些弹窗广告是可以在软件的设置里关闭的&#xff0c;但有些是流氓类型&#xff0c;无法设置。 1、有些是右下角弹窗&#xff0c;不提供关闭的设置&#xff08;能在图片上显示广告来源已经是比较良心了&#xff09…

金融机器学习:数据集划分与baseline模型

原创文章第115篇&#xff0c;专注“个人成长与财富自由、世界运作的逻辑&#xff0c; AI量化投资”。 在模型训练过程中&#xff0c;过拟合&#xff08;overfitting&#xff09;是非常常见的现象。所谓的overfitting&#xff0c;就是在训练集上表现很好&#xff0c;但是测试集…

学弟:功能测试转测试开发容易吗?

最近看到后台留言问&#xff1a;功能测试转测试开发容易吗&#xff1f; 从这个问题&#xff0c;我能读出一些信息如下&#xff1a; 不知道你从事测试工作多久了&#xff0c;可以看出您特别羡慕测试开发工程师&#xff1b;你可能一直从事功能测试工作&#xff0c;工作模式或大…

关于对 DeferWindowPos 的理解

DeferWindowPos 这个 API 的目标是&#xff1a;同一时间&#xff0c;移动多个子窗口。这在一定程度上减少了窗户移动时进行的重绘工作量。 修改我们之前的例子代码&#xff0c;如下图所示&#xff1a; >> 请移步至 topomel.com 查看图片 << 请注意&#xff0c;我…

基于蚁群算法的时延Petri网(ACOTPN)路径规划算法(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

ImmunoChemistry艾美捷抗体涂层缓冲液解决方案

使用ImmunoChemistry艾美捷ICT的抗体涂层缓冲液来节省试剂&#xff0c;增强特定信号&#xff0c;并延长涂层板的保质期。抗体涂层缓冲液最大限度地将抗体吸附到聚苯乙烯板上&#xff0c;并稳定抗体的三维结构以获得最佳性能。 ImmunoChemistry抗体涂层缓冲液&#xff0c;5X通过…

Debian11.5安装Podman并以多容器方式搭建LEMP环境

起因&#xff1a;之前在CentOS系统时代&#xff0c;写过一篇采用docker搭建LEMP环境的博客。现在时过境迁&#xff0c;CentOS系统&#xff0c;CoreOS系统&#xff0c;Docker&#xff0c;Podman管理工具的地位和应用&#xff0c;都有了极大变化&#xff0c;而我也转到了更为自由…

3d-face-reconstruction比较

摘要&#xff1a;比较近3年&#xff0c;6篇顶会3d-face-reconstruction重建效果。 1:Deep3D **发表时间:**2020 成就&#xff1a; 1&#xff09;在REALY和REALY (side-view)两个Benchmark上取得 State-of-the-art。 2&#xff09;官方github上成绩&#xff1a; 3DMM&#xf…

【学习笔记27】JavaScript字符串方法的练习

JavaScript字符串方法的练习一、统计字符串中每个字符出现的次数(以对象的形式记录)1、拿到字符串所有的值2、累加统计次数3、小优化二、反转字符串三、替换违禁词1、需求:将字符串中的6666, 替换为 "****"2、需求: 批量替换违禁词 [6666, 777]四、查询字符串1、模拟…

安全自动化企业网络架构 (毕设分享)

一、前言&#xff1a; 前段时间完成了自己的毕设项目——安全自动化企业网络架构。总的来说&#xff0c;该项目是一个对自己的挑战&#xff0c;其中涉及到Kubernetes容器云的搭建以及安全加固&#xff0c;DevOps CI/CD部署容器化监控平台&#xff0c;Django自动化运维平台开发…

CSS3------盒模型

盒模型 每个标签在浏览器上都被渲染成一个矩形个盒子&#xff0c;这个盒子有一个标准都组成结构&#xff0c;我们称为标准盒模型 盒模型构成 <!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8"> <meta name&qu…

【MM小贴士】物料主数据的中止与后继(2)

【日常吐槽】项目要上线了&#xff0c;70w的物料主数据导完了&#xff0c;有一部分小伙伴被隔离了&#xff0c;没人陪我玩&#xff0c;所以再补充几点日常blog。 很久以前发票了一篇博客&#xff0c;是关于物料主数据的中止与后继&#xff0c; 前期的blog可以参考【MM小贴士】…

Euler diagram

An Euler diagram (/ˈɔɪlər/, OY-lər) is a diagrammatic means of representing sets and their relationships. They are particularly useful for explaining complex hierarchies and overlapping definitions. They are similar to another set diagramming techniqu…

使用css形变实现一个立方体

关于 Nuxt.js 2016 年 10 月 25 日&#xff0c;zeit.co 背后的团队对外发布了 Next.js &#xff0c;一个 React 的服务端渲染应用框架。几小时后&#xff0c;与 Next.js 异曲同工&#xff0c;一个基于 Vue.js 的服务端渲染应用框架应运而生&#xff0c;我们称之为&#xff1a;…

速卖通跨境智星,速卖通合理补单技法

1、测评的用途   提升店铺信誉等级和好评&#xff0c;最重要的是提升产品权重和搜索排名&#xff0c;因为如果产品没有曝光&#xff0c;就没有流量&#xff0c;当然当有了权重和搜索排名&#xff0c;好评也是必不可少的。 2、爆款打造   很多新人在测评的时候会关注店铺排名…

Git版本控制工具使用

文章目录1. CICD系统构成和流程1.1 CICD来源及概念1.2 Git版本控制系统2. Git操作和使用git config (基本配置操作)git clone <repo URL\> (创建仓库|拷贝已有仓库)git branch (分支相关操作- 创建|查看|删除)git checkout (操作文件和分支)git add/commit (提交和修改-保…