C#基础8封装、继承、多态

面向对象特性:封装、继承、多态(思想)

三个特性主要目标:重用性(安全性)、灵活性和扩展性。

封装:类也体现封装
封装也需要考虑访问修饰符(思考封装的东西使用的范围)

封装不是封闭,只是在一定范围内保证代码的安全性,灵活性和复用性


一、封装

1.什么是封装?

其核心思想是 “隐藏对象的内部状态和实现细节,仅通过公开的接口(方法 / 属性)与外部交互”,目的是提高代码的安全性、可维护性和复用性。

2.封装实现:


字段和属性 :通过Get和Set方法实现对数据的读写操作,并可以在进行数据读写时添加自定义的逻辑。在C#中,属性可用于将实例变量封装到类中

访问修饰符: C#中有四种访问修饰符:public、private、protected和internal。这些访问修饰符可用于控制类中数据和方法的访问权限.

方法:实现细节可以隐藏起来并只暴露实现所需的最小接口。这样可以保证类的内部细节安全,并且仅在类的外部提供必要的接口.

二、继承

1.什么是继承?

继承:一个类继承另一个类的属性和方法

2.继承的作用:

解决类与类之间属性和方法重复的问题

3.继承的相关知识:

例如:被除数/除数=商
1.父类超类基类:被继承的类
相当于被除数
子类派生类:继承的类
相当于除数
2.继承格式:A类(子类):B类(父类)
继承是把被继承的属性和方法完全拿过来

3.继承关系建立后  子类拥有父类的成员  反之父类不继承子类成员。 父类私有成员 子类无法使用     其他访问权限可以被继承
父类私有成员子类无法使用 (父类私有成员可以被子类继承,但是因为权限问题不能直接使用,但是通过方法可以调用)父类不能继承子类中的成员

  4.一个父类可以同时被多个子类继承    子类可以间接继承父类  

  5.object是所有类的父类   如果一个类 没有明确继承关系   默认继承于object类

  6.C#中类与类之间是单继承关系(子类只能同时继承一个父类)   利用接口实现多继承(后续讲)
 protected 同一结构和派生类(子类)中使用
C#类与类的继承是单继承(重点)

所有的类默认继承Object,一个类继承另一个类后,object中的成员仍可以在子类中使用(还是单继承)
因为people作为子类继承了父类object的所有成员,man和woman又作为子类继承父类people中的所有成员,包括object中的成员

  7.创建子类对象时,系统默认先调用父类构造方法,然后再调用子类构造方法
  8.当父类有有参构造方法时.必须提供一个无参构造函数 供子类调用
  9.子类在调用其有参或者无参构造函数时,也会默认调用父类的 无参构造函数

静态的继承,子类继承成功,但是使用时静态只调用一次
实例则是调用一次,生成一次
一定会调用构造函数,但是父类存在有参的构造函数时,必须提供一个无参构造函数供子类调用(因为程序员自己定义有参构造函数后,系统默认的无参构造函数就会消失)如果不提供,需要提供与父类参数相同的子类有参构造函数
 10.如果想要调用父类有参构造函数  使用在子类构造函数后添加:base(参数名)

this

  • 当前类的对象
  • 静态成员方法中不能使用this关键字,this关键字只能在实例构造函数、实例方法或实例访问器中使用

this:当前类的对象,不能在静态成员方法中使用。this只能在实例成员中使用
this只能写在方法内部
.  作用:调用传递(实例方法隐藏一个关键字this,代表调用此方法的实例对象)
谁调用,this就是谁

静态调用不能用this,但是一定要调用实例对象,要明确实例对象

实例和静态都可以被继承,只不过实例用对象调,静态用类调

base

1.  base 代表父类的对象

2.base关键字用于从派生类中访问基类的成员;

base写在子类中
父类的功能不能完全满足时,子类中重新写父类的方法,父类的基础功能会被隐藏

例如上图,重新写父类方法,父类基础功能被改变,原有的父类功能被隐藏消失了。但是如果想父类基础功能不消失的同时增加新的功能需要base

3.派生类对象调用基类构造函数;

4.调用基类上已被重写的方法

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

base和this区别:this本类当前类对象,base父类对象

base在有参构造函数中的应用例题:

 //     给 Car 类添加带参构造函数。让 BMW 和 aodi 子类通过 base 调用父类构造函数,
 //     简化代码。要求:创建 子类 对象时,直接给型号、价格、速度赋值
 public class Car1 
 {

   //  型号、价格、速度
     public string Model { get; set; }
     public int Price { get; set; }
     public int Speed { get; set; }


     public Car1(string model, int price, int speed)
     {
         Model = model;
         Price = price;
         Speed = speed;
     }
 }


 public class BMW : Car1
 {
     public BMW(string model, int price, int speed):base(model,price,speed)
     {
      
     }
 }


 public class Aodi1 : Car1
 {
     public Aodi1(string model, int price, int speed) : base(model, price, speed)
     {

     }
 }

三、多态

什么是多态?

即一个接口,多个功能  同一种操作作用于不同的对象,可以有不同的解释,产生不同的执行结果

包含:重写(覆盖)、抽象类、接口、重载

1、重载:

方法重载:在一个类或子类中函数名相同,参数类型或顺序不同构成重载,与返回类型无关

访问修饰符不构成重载
静态非静态不构成重载
返回值类型不构成重载
重载只和名字,参数类型及顺序有关

2、覆盖

在子类和父类中,子类中的方法名称和父类方法名称相同,参数相同  

在子类中写一个和基类一样名字(参数不同也算)的非虚函数,会让基类中的函数被隐藏,编译后会提示要求使用New关键字

 覆盖是非法的重写
覆盖和静态static ,返回值类型 ,访问修饰符无关
覆盖只与方法名,参数有关

重载与覆盖区别:

覆盖:子类与父类方法名称,参数都相同
重载:方法名称相同,但是参数,顺序和个数不同(即方法签名不同)

方法的签名:不能重复   方法名+参数列表(个数,顺序,类型)
覆盖:子类写与父类一样的方法时,会产生警告,但是配合new就不会产生警告

(拓展:new只能覆盖已经实现过的方法,即覆盖实例方法、不能实例化的类有静态类也有抽象类
但是抽象类可以赋值为实现抽象类的类,因为可以向上隐式转换(小转大))

配合new的覆盖写法(与父类base相配合):

3、重写

重写是合法的覆盖。

在子类和父类中,子类中的方法名称和父类方法名称相同,参数相同  

使用关键字 virtual,将父类的方法标记为虚方法,用 override  关键字,虚方法可以被子类重写

4、抽象类

 //1关键字 abstract

//抽象类格式示例:

public abstract class BaseClass
{

}
 //2.不能被实例化    不能创建对象  抽象类的存在 就是为了继承。
 //3.普通类和抽象类都可以继承抽象类,在另一层面上讲也可以说普通类相当于抽象类的多态

  //4.抽象类可以包括抽象方法和抽象属性但是不能定义抽象字段,或者能定义普通方法属性字段 

抽象方法没有实现过程(抽象方法天生就是虚方法,override只能重写虚方法)

 //5.普通类继承了具有抽象成员的 抽象类  必须在其内部重写抽象的抽象成员  (使用override)

抽象类定义规则,具体规则的完成由子类完成
继承抽象类时,抽象类里的普通方法,字段,属性照样继承,但是抽象类里的抽象属性和方法必须在子类里实现重写一次。
override实现父类的抽象方法
例如下图子类继承抽象类写法

注意:抽象类的抽象属性和方法实现都要子类实现,包括父类的父类中的抽象属性和方法最好在最后子类继承时实现,前面的父类也能实现,但是会固定内容,下一个子类无法使用,所有最好实现放在最后一个子类中进行实现

 //6.静态成员不能定义为抽象

5、接口

含义:接口和抽象类都是为其子类提供语法合同(模板)

接口定义了所有类继承接口时应遵循的语法合同 .用接口可以使程序更加清晰和条理化  与抽象类功能相似

1.接口使用 interface 关键字声明,它与类的声明类似。接口声明默认是 public 的,名字要求:大写I开头

*(接口默认internal,接口成员默认public,类默认internal,类成员默认private)

2.接口只包含了成员的声明( 方法 属性声明) 

普通类实现接口内容像继承抽象类一样,需要对接口内的方法属性进行实现(加上访问修饰符)

3.接口中只能包含方法、属性、索引器和事件的声明。不允许声明成员上的修饰符,即使是pubilc都不行,因为接口成员总是公有的,也不能声明为虚拟和静态的(即virtual和static不能存在)。如果需要修饰符来声明,最好让实现类明。

4.一个类 可以继承多个接口  (接口就是c#实现多继承的方式)

接口是实现类多继承的方式
类与类都是单继承方式

5.如果一个类继承另一个类 也同时继承接口   : 后必须先写类的继承    接口继承 以逗号分隔

类继承接口时同时继承object类,虽然类与类是单继承,但是接口和类不同,两者是不同的两条线,所有同时继承接口和object类
如果一个类继承另一个类同时继承一个接口,必须先写继承的类,然后逗号,接口
例如:public class DogClass:BigDog,IAnimal

6.接口中定义的成员 需要继承类 来进行实现

普通类继承接口过来后,可以在这个类里进行虚方法virtual重写

7.接口也可以继承接口

接口和抽象类 区别和相同点

相同点: 不能实例对象    都可以被继承   都可以给继承类提供成员模板

不同点:接口只能有成员定义  抽象类 也可以包含成员的实现    接口可以实现多继承  抽象类只能单继承

6、密封类 

密封类:限制继承性,不能被作为基类被继承,但是可以继承别的类和接口
string密封类

     1.密封类可以用来限制继承性
     2.声明密封类时需要使用sealed关键字
     3.密封类和普通类一样 都可以定义属性和方法
     4.密封类不能作为基类被继承,但它可以继承别的类或接口
     5.密封类可以实例化对象  系统中String 就是密封类
     6.在密封类中不能声明受保护成员或虚成员(密封类中不能用与继承相关的东西即现学的protected和virtual不能用)


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值