十三、类的继承、访问级别

类的继承与访问控制

在这里插入图片描述

类的继承

  • 使用sealed修饰的类,是私有类,不能作为基类使用
  • C#中一个类,只能有一个父类,但是可以实现多个接口
  • 子类的访问级别不能超过父类的访问级别
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HelloOOP {
    internal class Program {
        static void Main(string[] args) {
            //从代码上验证继承关系
            Type t = typeof(Car);
            Type tb = t.BaseType;
            Type ttTop = tb.BaseType;
            Console.WriteLine(ttTop.FullName);
            /* 所有的类都继承自Object
             * 并且Object上面就没有父类了,Object是处于最顶端的
             */
            Console.WriteLine(ttTop.BaseType == null);

            /* 是一个 is a, 一个子类的实例也是父类的实例
             * 一个学生一定是一个人
             * 一个父类的实例不一定是子类的实例
             * 一个人不一定是一个学生
             */
            Car car = new Car();
            Console.WriteLine(car is Vehicle);


        }
    }
    class Vehicle { }
    //Car类继承自Vehicle类
    class Car : Vehicle { }

    // 1.私有类,不能当做基类来使用
    sealed class Bycicle { }
}

成员的继承与访问

继承

继承的本质:派生类在基类已有的成员的基础之上,对基类进行的横向和纵向上的扩展

  • 当继承发生的时候,子类对父类所有的成员是全盘继承的,除了三种东西不会被继承

    • 静态构造器:用于初始化类的静态数据。
    • 实例构造器:在创建类的新实例时调用。 每个类都必须定义自己的构造函数。
    • 析构函数(终结器):由运行时的垃圾回收器调用,用于销毁类实例。
  • 在派生的过程当中,我们进行的是扩展

    也就是不能对父类的成员进行去除,只能扩展,这是静态类型语言(c++、c#、Java)的特点

    而某些动态语言(python、JavaScript)则可以去除父类的成员

  • 横向扩展即,类成员的增加;纵向扩展即,类成员的重写

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HellloAccess {
    internal class Program {
        static void Main(string[] args) {
            Car car = new Car();
            Console.WriteLine(car.Owner);

        }
    }

    class Vehicle {
        public Vehicle()
        {
            this.Owner = "N/A";
        }
        public string Owner { get; set; }
    }
    class Car : Vehicle { 
        public Car() {
            //this.Owner = "Car Owner";
        }
        public void ShowOwner() {
            //只能访问上一级的对象
            Console.WriteLine(base.Owner);
            /* 创建子类对象的时候,是从基类的构造器开始
             * 一层一层往下构造的,最终构造出来子类的对象
             */
            Console.WriteLine(this.Owner);
            /* 当前这个base.Owner和this.Owner在这个例子中
             * 都指向的是同一个字符串即"Car Owner"
             * 因为子类中的构造器把原来的Owner覆盖了
             */
        }
    }
}

实例构造器无法被继承

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HellloAccess {
    internal class Program {
        static void Main(string[] args) {
            Car car = new Car("Ygc");
            Console.WriteLine(car.Owner);
            /* 实例构造器无法被继承
             * 但是会先调用父类的实例构造器,然后再调用子类的实例构造器
             */
        }
    }

    class Vehicle {
        public Vehicle(string owner)
        {
            this.Owner = owner;
        }
        public string Owner { get; set; }
    }
    class Car : Vehicle {
        /* 当父类的构造器,是带参数的。
         * 那么父类的默认的构造器就会被覆盖掉
         * 那么此时调用子类的默认构造器是不行的
         * 因为调用子类的默认构造器,会先调用父类的默认构造器
         * 而此时,父类的默认构造器是不存在的,会发生冲突
         */

        //更改的办法:
        public Car() : base("N/A") {
            //this.Owner = "Car Owner";
        }
        //或者写一个带参数的构造器
        public Car(string owner) : base(owner)
        {
        }

        public void ShowOwner() {
            Console.WriteLine(this.Owner);
        }
    }
}

继承中的访问级别

派生类和派生记录不能具有高于其基类型的可访问性。

虽然基类的其他所有成员都可供派生类继承,但这些成员是否可见取决于它们的可访问性。 成员的可访问性决定了其是否在派生类中可见。

类成员的访问级别是以类的访问级别作为上限的。

internal class Student{
    public string name;
    //所以这个类成员是不能被其他程序集所访问的
}

父类中的私有字段被限制在了父类的类体中,子类是不能直接访问的,但是是继承了的

以下代码可以证明:


namespace MyLib
{
    public class Vehicle
    {
        private int _rpm;
        //命名前面加_表示,这是一个私有字段
        public void Accelerate() {
            _rpm += 1000;
        }
        //该属性返回的是私有字段/ 100之后的值
        public int Speed {  get { return _rpm / 100; } }

    }

    public class Car : Vehicle{  }
}


using System;
using MyLib;

namespace HellloAccess {
    internal class Program {
        static void Main(string[] args) {
            Car car = new Car();
            car.Accelerate();
            car.Accelerate();
            Console.WriteLine(car.Speed);
            /* 使用car对象调用父类的属性,能够成功返回
             * 说明,父类的私有字段实际上也是被子类所继承的,
             * 只是不能被car类所访问
             */
        }
    }
}

类成员的访问级别:

  • 只有在基类中嵌套的派生类中,私有成员才可见。 否则,此类成员在派生类中不可见。

    private会把访问级别限制在类的类体中,所以只有嵌套的派生类才能访问

    public class A
    {
        private int _value = 10;
    
        public class B : A
        {
            public int GetValue()
            {
                return _value;
            }
        }
    }
    
    public class C : A
    {
        //    public int GetValue()
        //    {
        //        return _value;
        //    }
    }
    
    public class AccessExample
    {
        public static void Main(string[] args)
        {
            var b = new A.B();
            Console.WriteLine(b.GetValue());
        }
    }
    // The example displays the following output:
    //       10
    
  • 受保护成员仅在派生类中可见。

    会把访问级别限制在继承链上,并且可以夸程序集

    protected更多的用在方法上

    namespace MyLib
    {
        public class Vehicle
        {
            protected int _rpm;
            private int _fuel;//表示油量
            //加油的方法
            public void Refuel() {
                _fuel = 100;
            }
            /* 烧油方法
             * 即不想暴露给外界,引发错误的调用
             * 又想继承给子类继续调用
             * 于是就用,protected访问修饰符
             */
            protected void Burn(int fuel) {
                _fuel -= fuel;
            }
            public void Accelerate() {
                Burn(1);//普通加速耗油1
                _rpm += 1000;
            }
    
            public int Speed {  get { return _rpm / 100; } }
    
        }
    
        public class Car : Vehicle{  
            public void TurboAccelerate() {
                //烧两次油,加速3000
                Burn(2);//涡轮增压加速,耗油2
                _rpm += 3000;
            }
        }
    }
    
    using System;
    using MyLib;
    
    namespace HellloAccess {
        internal class Program {
            static void Main(string[] args) {
                Car car = new Car();
                car.Refuel();//先加油
                car.TurboAccelerate();//再加速
                Console.WriteLine(car.Speed);
    
                Bus bus = new Bus();
                bus.Refuel();
                bus.SlowAccelerate();
                Console.WriteLine(bus.Speed);
                Console.ReadKey();
            }
        }
        class Bus: Vehicle {
            public void SlowAccelerate() {
                //夸程序集,仍然可以调用父类的protected的成员
                Burn(1);
                _rpm += 500;
            }
        }
    }
    
    
  • 内部成员仅在与基类同属一个程序集的派生类中可见, 在与基类属于不同程序集的派生类中不可见。

  • 公共成员在派生类中可见,并且属于派生类的公共接口。 可以调用继承的公共成员,就像它们是在派生类中定义一样。

    public class A
    {
        public void Method1()
        {
            // Method implementation.
        }
    }
    
    public class B : A
    { }
    
    public class Example
    {
        public static void Main()
        {
            B b = new ();
            b.Method1();
        }
    }
    

访问修饰符(全)

这一段是我抄的微软官方文档

  • public:同一程序集中的任何其他代码或引用该程序集的其他程序集都可以访问该类型或成员。 某一类型的公共成员的可访问性水平由该类型本身的可访问性级别控制。
  • private:只有同一 classstruct 中的代码可以访问该类型或成员。
  • protected:只有同一 class 或者从该 class 派生的 class 中的代码可以访问该类型或成员。
  • internal:同一程序集中的任何代码都可以访问该类型或成员,但其他程序集中的代码不可以。 换句话说,internal 类型或成员可以从属于同一编译的代码中访问。
  • protected internal:该类型或成员可由对其进行声明的程序集或另一程序集中的派生 class 中的任何代码访问。
  • private protected:该类型或成员可以通过从 class 派生的类型访问,这些类型在其包含程序集中进行声明。

在这里插入图片描述

各种东西的默认访问级别

默认情况下,类成员和结构成员(包括嵌套的类和结构)的访问级别为 private。 不能从包含该类型的外部访问私有嵌套类型。

在这里插入图片描述

面对对象的实现风格

面向对象语言学习方法的问题

不要因为学了某个语言,就极大的夸赞该语言的优点,而藐视其他语言的缺点。

C#中的派生和继承,仅仅只是众多语言派生和继承的一种风格,还有其他的派生和继承的风格。

**C#使用的是Class-based风格,基于类的封装、继承和多态。**目前是主流,C++,C#,Java。

JavaScript使用的是Prototype-based风格,基于原型的封装、继承和多态的方式

Java不是单根的类型系统,它的引用类型是单根的,但是它还有一套系统,叫基本类型系统。


有部分内容,我是抄的微软的官方文档。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HDFS简介与部署以及故障排错(超简单)

文章目录 一、HDFS介绍1、简介2、结构模型3、文件写入过程4、文件读取过程5、文件块的存放6、存储空间管理机制6.1 文件删除和恢复删除6.2 复制因子配置6.3 文件命名空间6.4 数据复制机制 二、环境搭建(单机版)1、修改主机名2、配置ssh免密登录3、Hadoop…

HTML表单标签,web前端开发新技术

1、ant-design的使用总结及常用组件和他们的基本用法? ant-design为React,Angular和Vue都提供了组件,同时为PC和移动端提供了常用的基础组件。ant-design提供的demo非常的丰富并且样式能够基本的覆盖开发需求。antd的Demo因为是多人编写的,…

(vue)适合后台管理系统开发的前端框架

(vue)适合后台管理系统开发的前端框架 1、D2admin 开源地址:https://github.com/d2-projects/d2-admin 文档地址:https://d2.pub/zh/doc/d2-admin/ 效果预览:https://d2.pub/d2-admin/preview/#/index 开源协议:MIT 2、vue-el…

自动化测试基础——Pytest框架之YAML详解以及Parametrize数据驱动

文章目录 一、YAML详解1.YAML作用2.YAML语法结构3.YAML数据类型3.1.对象3.2.数组3.3.标量 4.YAML的引用5.YAML类型转换 二、YAML的读写与清空1.YAML的读2.YAML的写3.YAML的清空 三、pytest的parametrize简单数据驱动四、pytest的parametrize结合yaml实现数据驱动五、解决pytest…

LeetCode Python - 36.有效的数独

目录 题目答案运行结果 题目 请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&#xff08…

CSS 选择器的常见用法

CSS选择器的主要功能就是选中⻚⾯指定的标签元素.选中了元素,才可以设置元素的属性. CSS选择器主要分以下⼏种: 1. 标签选择器 2. class选择器 3. id选择器 4. 复合选择器 5. 通配符选择器 <body><div class"font32"> 我是一个div,class为front32</…

D*算法超详解 (D星算法 / Dynamic A*算法/ Dstar算法)(死循环解决--跟其他资料不一样奥)

所需先验知识&#xff08;没有先验知识可能会有大碍&#xff0c;了解的话会对D*的理解有帮助&#xff09;&#xff1a;A*算法/ Dijkstra算法 何为D*算法 Dijkstra算法是无启发的寻找图中两节点的最短连接路径的算法&#xff0c;A*算法则是在Dijkstra算法的基础上加入了启发函数…

docker-compose Install rustdesk

RustDesk RustDesk 是一款开源的远程支持和远程桌面工具,它旨在为用户提供便捷的远程协助和远程访问功能。 默认情况下,hbbs 监听21115(tcp), 21116(tcp/udp), 21118(tcp),hbbr 监听21117(tcp), 21119(tcp)。务必在防火墙开启这几个端口, 请注意21116同时要开启TCP和UDP。…

Mint_21.3 drawing-area和goocanvas的FB笔记(四)

Cairo图形输出 cairo的surface可以是pixbuf, 可以是screen, 可以是png图&#xff0c;也可以是pdf文件 、svg文件、ps文件&#xff0c;定义了surface就可以用cairo_create(surface)产生cairo context, 操作cairo context就可以方便地在surface上画图&#xff0c;如果surface是p…

微服务知识03

1、ES搜索引擎,高性能的分布式搜索引擎,底层基于Lucene 主要用于应用程序中的搜索系统 日志收集 2、基础概念 3、ES处理流程 5、下载中文分词器 Releases infinilabs/analysis-ik GitHub 6、分词模式 最细粒度拆分、智能分词 7、Elaticsearch配置流程 (1)把文件拖进…

2024 年适用于 Windows 和 Mac 的最佳数据恢复软件

您刚刚与朋友参加了一次难忘的告别聚会回来。您已经拍摄了数百个美好瞬间&#xff0c;并将它们保存在您的设备中&#xff0c;并渴望与您所爱的人分享。 但随后&#xff0c;您突然不小心从电脑中删除了整个相机文件夹。现在这是我们许多人面临的最严重的问题&#xff0c;因为我…

Stable Diffusion ———LDM、SD 1.0, 1.5, 2.0、SDXL、SDXL-Turbo等版本之间关系现原理详解

前言 2021年5月&#xff0c;OpenAI发表了《扩散模型超越GANs》的文章&#xff0c;标志着扩散模型&#xff08;Diffusion Models&#xff0c;DM&#xff09;在图像生成领域开始超越传统的GAN模型&#xff0c;进一步推动了DM的应用。 然而&#xff0c;早期的DM直接作用于像素空…

2024年2月份微软安全通告

文章目录 &#xff08;一&#xff09; 漏洞概要&#xff08;二&#xff09; 漏洞数据分析1、漏洞数量趋势2、历史微软补丁日二月漏洞对比3、漏洞数量分析 &#xff08;三&#xff09; 重要漏洞分析1、漏洞分析2、影响范围3、修复建议 &#xff08;一&#xff09; 漏洞概要 202…

SanctuaryAI推出Phoenix: 专为工作而设计的人形通用机器人

文章目录 1. Company2. Main2.1 关于凤凰™ (Phoenix)2.2 关于碳™(Carbon)2.3 商业化部署2.4 关于 Sanctuary Corporation 3. My thoughtsReference彩蛋&#xff1a;将手机变为桌面小机器人 唯一入选《时代》杂志 2023 年最佳发明的通用机器人。 称机器人自主做家务的速度和灵…

5G 网络切片VLAN ID配置错误导致业务不可用

【摘要】随着电联5G共建共享工作的开展&#xff0c;无法及时有效观测到单逻辑站点的相关指标&#xff0c;导致单运营商用户业务出现异常。本案例中着重对单运营商用户无法使用网络进行相关参数排查&#xff0c;从KPI性能指标结合故障告警发生时间&#xff0c;从而分析由于网络切…

BUUCTF-DASBOOK1

[第一章][1.3.5 案例解析][极客大挑战 2019]Http 1 1.启动靶机 2.查看源代码&#xff0c;发现有链接 3.点击链接&#xff0c;跳转页面有提示&#xff0c;意思是&#xff1a;它并不来自于https:/Sycsecret.buuoj.cn 打开hackbar&#xff0c;如图所示&#xff0c;然后执行 4.得到…

对于爬虫的学习

本地爬取 package MyApi.a08regexdemo;import java.util.regex.Matcher; import java.util.regex.Pattern;public class RegexDemo03 {public static void main(String[] args) {//要求&#xff1a;找出里面所有javaxxString str"Java自从95年问世以来&#xff0c;经历了…

html标签元素类型,一个前端妹子的面试笔记

计算机网络篇 HTTP HTTP 报文结构是怎样的&#xff1f;HTTP有哪些请求方法&#xff1f;GET 和 POST 有什么区别&#xff1f;如何理解 URI&#xff1f;如何理解 HTTP 状态码&#xff1f;简要概括一下 HTTP 的特点和缺点&#xff1f;对 Accept 系列字段了解多少&#xff1f;对于…

【Linux篇】Linux下的第一个小程序--进度条 蹦迪炫彩进图条

&#x1f49b;不要有太大压力&#x1f9e1; &#x1f49b;生活不是选择而是热爱&#x1f9e1; 文章目录 Linux下第一个小程序&#xff1a;进度条两个背景知识缓冲区回车和换行是一个概念&#xff1f; 进图条原理进度条代码效果其他玩法&#xff1a;蹦迪版进度条 Linux下第一个小…

CSS常用五类选择器,附面试题

学习路线 第一阶段&#xff1a;网页制作 HTML&#xff1a;常用标签&#xff0c;锚点&#xff0c;列表标签&#xff0c;表单标签&#xff0c;表格标签&#xff0c;标签分类&#xff0c;标签语义化&#xff0c;注释&#xff0c;字符实体 CSS&#xff1a;CSS介绍&#xff0c;全局…