当前位置: 首页 > news >正文

C#面向对象的三特性其一:封装

一.类与对象


1.类的概念

类是 具有相同特征  具有相同行为 的一类事物的抽象

类是对象的模板,可以通过类来创建对象.

类的关键词是class


2.类申明的位置

类申明在 namespace 语句块中

同一语句块中不能出现明名重复的类


3.类声明的语法

public class classname{ //特征——成员变量//行为——成员方法//保护特征——成员属性//构造函数和析构函数//索引器//运算符重载//静态成员}//命名用帕斯卡命名法

4.(类)对象

类的申明 和 类对象(变量) 的申明是两个概念

类的申明类似 枚举结构体 的申明,相当于申明了一个自定义变量类型

而对象 是类创建出来的

相当于申明了一个指定类的变量

类创建对象的过程 一般称为实例化对象

类对象 都是引用类型


5.实例化对象基本语法

类名 变量名;

类名 变量名 = null;(null代表空)

类名 变量名 = new 类名();

例:

 //分配的内存空间为空Person p;Person p1 = null;//分配了内存空间Person p2 = new Person();Person p3 = new Person();//要几个对象就new几个对象

注意!  实例化后的两个对象可视作不同的个体  他们之间的属性互不相关


二.成员变量与访问修饰符


1.成员变量的概念

成员变量是 申明在类语句块中的用于描述成员特征的变量

可以是任意的变量类型包括自己所处的类

注意:不能在类中实例化与自己同类的变量!!!

//定义一个位置结构体struct Position{//定义变量public int x;public int y;//构造函数position (x,y);//函数方法}//定义一个性别枚举    enum E_SexType {man,woman,}class person{int age;string name = "";  //可以初始化E_SexType sex;Position pos;  person[] boyfriend;person girlfriend = new person; //初始化后会报错!!}

2.访问修饰符 (3p)

[1] public -- 公共的 自己(内部) 和 别人(外部) 都能访问和使用

[2]private -- 私有的 自己(内部)才能访问和使用,不写默认为private

[3]protected -- 保护的 自己(内部) 和 子类 才能访问和使用

3.成员变量的使用和初始值

使用:先实例化

person p = new person();

然后

p.age = 10;

值类型 数字类型默认为0

            bool类型默认为false

引用类型默认为 null

判断默认值的小技巧

例如:如果我们要了解bool类型的默认值:

Console.WriteLine(default(bool));


三.成员方法


1.概念

成员方法(函数) 用于表现对象行为

[1]申明在类语句块中

[2]是用来描述对象行为的

[3]规则和函数申明规则相同

[4]受到访问修饰符规则影响

[5]返回值参数不做限制

使用方法例如

class Person{//判断是否成年public bool IsAdult(){return age >= 18;}//说话行为public Speak(string str){IsAdult();Console.WriteLine("{0}",str);}//成员变量初始化public string name;    public int age;}static void Main(string[] args){//使用成员方法//先实例化对象Person p = new person();//成员变量赋值p.name = "小明";p.age = 18;使用说话方法p.Speak("我爱你");if(p.IsAdult()){p.Speak("我要耍朋友");}}

2.应用

我们可以利用这一特性来封装函数,例如:

在数组的增删查改中

我们可以定义类的数组然后

class Person{//定义一个新的成员方法public void AddFriend(person p){//传入的值为空时,仅开辟一个新空间if(friends == null){friends = new Person[]{p};}else {//新建一个数组Person[] newFriends = new Person[friends.Length+1];//搬家for(int i = 0 ; i < friends.Length ; i++){newFriends[i] = friends[i]; }//把新加的朋友放到最后一个newFriends[newFriends.Length - 1] = p;//地址重新定向friends = newFriends;}}//成员变量初始化public string name;public int age;public person[] friends; }static void Main(string[] args){Person p1 = new Person();person p2 = new Person();p2.name = "梁非凡";p2.age = 16;p1.AddFriends(p2);//打印friendsfor(int i = 0 ; i < p.friends.Length ;i++){Console.WriteLine(p.friends[i].name);}}   

四.构造函数、析构函数、垃圾回收机制


1.构造函数(与结构体类似)

【1】 基本概念

在实例化对象时 会调用用于初始化的函数

如果不写 默认存在一个无参构造函数

namespace 例
{class Person{public string name;public int age;//无参构造函数public Person(){name = "小明";age = 18;}}class program{static void Main(string[] args){Person p = new Person();Console.WriteLine(p.age);}}
}

【2】构造函数的写法

1.无返回值

2.函数名和类名必须相同

3.没有特殊需求时,访问修饰符默认public

class Person

{

    public string name;

    public int age;

   //有参构造函数(函数重载)

    public  Person(string str,int age)

    {

        this.name = "str";

        this.age = age;

    }

   //类允许声明无参构造函数,结构体不行

     public Person()

      {

           name = "小明"

           age = 18;

      }

}

4.构造函数可以被重载

5.this代表当前调用该函数的对象自己

外部调用时:

Person p =  new person("小华",19);

注意:

如果不自己写无参构造函数而写了有参构造函数

会失去默认的无参构造


【3】构造函数的特殊写法

在之前的有参函数的基础上写  :this()   ,并去掉{}里的内容

在断点运行时直接执行了

public Person(){name = "小明";age = 18;}

通过调用堆栈发现上一步是运行到了 :this()

  public Person(int age,string str):this(){Console.WriteLine("test success");}

通过调用堆栈窗口发现进入构造函数的入口是

Person p1 = new Person(21,"小明");

换句话说,在new一个类时,会根据new中的参数来找到参数构造函数,:this() 的作用是跳过执行new对应的构造函数而先执行 :this() 括号内的构造函数

以此来节约代码量


2.析构函数(仅了解)

基本概念

当引用类型的堆内存被回收时,会调用该函数

对于需要手动管理内存的语言(比如C++),需要在析构函数中做一些内存回收处理

但是C#中存在自动垃圾回收机制GC

所以我们几乎不会怎么使用析构函数,除非你想在某一个对象被垃圾回收时,做一些特殊处理

注意:

在unity开发中析构函数几乎不会使用,所以该知识制作了解即可

基本语法

~类名()

{

}

当垃圾真正被回收的时候才会调用的函数


3.垃圾回收机制 GC(C#再带的垃圾回收机制)

垃圾回收,英文写作GC(Garbage Collector)

垃圾回收的过程是在遍历堆(Heap)上动态分配的所有对象

通过识别他们是否被引用 来确定那些对象是垃圾,那些对象仍要被使用

所谓的垃圾就是没有被任何变量,对象引用的内容

垃圾就需要被回收释放

垃圾回收有很多种算法,比如

引用计数(Reference Counting)

标记清除(Mark Sweep)

标记整理(Mark Compact)

复制集合(Copy Collection)

注意:GC只负责堆(heap)内存的垃圾回收

应用类型都是存在堆(Heap)中的,所以他的分配和释放都是通过垃圾回收机制来管理的

栈(Stack)上的内存是由系统自动管理的

值类型是在栈(Stack)中分配内存的,它们有自己的生命周期,不用对他们进行管理,会自动分陪和释放。

C#中内存回收机制的大概原理

0代内存   1代内存   2代内存

代的概念:

代是垃圾回收机制的一种算法(分代算法)

新分配的对象都会被配置在第0代内存中

每次分配都可能进行垃圾回收以释放内存(0代内存满的时候)

在一次内存回收过程开始时,垃圾回收器会认为堆中全是垃圾,会进行以下两步

1.标记对象 从根(静态字段、方法参数)开始检查引用对象,标记后为可达对象,未标记为不可达对象(垃圾)

2.搬迁对象压缩堆  (挂起执行托管代码线程) 释放未标记的对象 搬迁可达对象 修改引用地址

大对象总是被认为是第二代内存 目的是减少性能损耗,提高性能

不会对大对象进行压缩搬迁  85000字节 (83kb)以上的对象为大对象

手动执行,垃圾回收机制(在游戏开发中GC通常在加载时使用)

//手动触发垃圾回收的方法
//一般情况,不频繁使用GC.Collect();

五.成员属性


【1】基本概念

1.用于保护成员变量

2.为成员属性的获取和赋值添加逻辑处理

3.解决3p的局限性

public——内外访问

private——内部访问

protected——内部和子类访问

属性可以让成员变量在外部

【只能获取 不能修改】 或者 【只能修改 不能获取】

【2】基本语法

访问修饰符 属性类型 属性名

{

  get{}

  set{}

}

依旧是申明一个person

 class Person{private string name;private int age;private int money;private bool sex;//属性命名的方法使用 帕斯卡命名法public string Name{get {//可以再返回之前添加一些逻辑规则//意味着 这个属性可以获取的内容return name;}set {//可以在设置之前添加一些逻辑规则//value关键字 用于表示外部传入的值name = value;//value的类型必须和属性的类型一致}}}

【3】成员变量使用

 Person P = new Person();P.Name = "小明";Console.WriteLine(P.Name);

在执行此段代码时,p.Name 会跳到成员属性中

把“小明”赋给value 然后再到get返回,可以使用这一方法对数据进行处理

处理操作1 让成员变量money一定大于等于0

 public int Money{get{return money;}set{if (value<0){value = 0;Console.WriteLine("钱不能少于0");}money = value;}}

处理操作2 实现简单的加密

public int Age{           get{//解密处理return age-5;}set {//加密处理age = value + 5;}    }

此操作可以使存在内存中的不为原来的值

【4】成员属性如何解决3p的局限性

可以在get 和 set前加访问修饰符

不加,默认与成员属性自带的修饰符相同

所以通过private和public,我们可以解决3p的局限性

外部只能使用不能修改

 

 外部只能修改不能使用

注意:

1.默认不加 会使用属性声明时的访问权限

2.加的访问修饰符要低于属性的访问修饰符

public的权限是最高的

不能让get 和 set 的访问权限都低于属性的访问权限

同理,不能与属性的访问修饰符重复

一般不会出现两个访问修饰符

【5】get和set 可以只有一个

 一般只会出现只有get的成员变量(只能得不能改)

 public bool Sex{get {return sex;}}

【6】自动属性

作用:外部能得不能改的特征

如果类中有一个特征只是希望内部能得不能改的 又没有什么特殊处理

那么可以直接使用自动属性

        public float Height{get;private set;}

属性可以代替成员变量但全无必要


六.索引器


1.索引器的基本概念

让对象可以像数组一样通过索引访问其中元素,让程序看起来个更直观,易于编写


2.索引器语法

访问修饰符 返回值 this  [参数类型 参数名1,参数类型 参数名2.....]

{

get{}

set{}

}

class person{private string name;private int age;private Person[] friends;public Person this[int index]{get {return friends[index];            }set{friends[index] = value;}    }}

3.索引器使用

 Person P = new Person();P[0] = new Person();Console.WriteLine(P[0]);

4.索引器中写逻辑

class person{private string name;private int age;private Person[] friends;public Person this[int index]{get {if(friends == null || friends.Length - 1 < index)return null;return friends[index];            }set{if (friends = null){friends = new Person[] {value};}else if (index > friends.Length - 1){//自己定一个规则 如果索引越界 就默认把最后一个朋友顶掉 friends[friends.Length - 1] = value;}friends[index] = value;}    }}

5.索引器重载(实现二维数组)

private Person this[int i,int j]{get{return array[ i , j];}set{array[i , j] = value;}}

 返回值可以是其他类型

public string this[string str]
{get{switch (str){case "name":return this.name;default:return age.ToString();}}set{array[i , j] = value;}
}

总结:

索引器的作用

 让我们以中括号的形式范围自定义类中的元素 规则自己定 使用

 适合在类中有数组变量时使用 可以方便地访问和进行逻辑处理

固定写法

访问修饰符 返回值 this[参数列表]

get和set 语句块

可以重载

注意:结构体中也支持索引器


七.静态成员


1.概念

静态关键字 static

用static修饰的 成员变量、方法、属性等

静态成员的特点是:直接用类名点出使用


2.早已出现过的静态类

如之前的 Console 就是一个静态类


3.自定义静态成员

class Test
{//静态成员变量public static float PI = 3.1415926f;//成员变量public int testInt = 100;//静态成员方法 public static float CalcCircle(float r){return PI * r * r;}//普通成员方法public void TestFun(){Console.WriteLine("123");}
}

4.静态成员的使用

直接类名 . 就可以使用

Console.WriteLine(Test.PI);
Console.WriteLine(Test.CalcCircle(2));

静态成员和非静态成员的区别 

静态成员非静态成员
使用前无需先实例化使用前需要实例化
静态成员方法无需实例化成员方法需要实例化

 5.为什么可以直接点出来使用

记住!

程序不是无中生有的

我们要使用的对象,变量,函数都是要在内存中分配内存空间的

之所以要实例化对象,目的就是要分配内存空间,在程序中产生一个抽象的对象

静态成员的特点

程序开始运行时,就会分配内存空间,所以我们就能直接使用。

静态成员和程序共生死

只要使用了它,直到程序结束时内存空间才会被释放

所以一个静态成员就会有自己唯一一个“内存空间”

让静态成员有了唯一性

在任何地方使用都是用的小房间里的内容,改变了它也就是改变了小房间里的内容。


6.静态函数中不能使用非静态成员

成员变量只有先将对象初始化后,才能点出来使用 不能无中生有

不能直接使用 必须要先才能使用

原因:二者生命周期不同


7.非静态函数可以使用静态成员

因为静态成员可以在整个程序的生命周期中存在,因此可以使用

原因:二者生命周期不同


8.静态成员的作用

静态成员常用于 固定数值的的申明,如加速度,PI

静态成员方法 常用于唯一方法申明 比如 相同规则的数学计算相关函数


9.常量和静态变量

const(常量)可以理解为一种特殊的static (静态)

相同点

他们都可以通过类名点出使用

不同点

1.const 必须先初始化 不能修改 static没有这一规则

2.const 只能修饰变量 static可以修饰很多

3.const可以写在访问修饰符后 static没有这一要求


八.静态类和静态构造函数


1.概念

用static修饰的类

·特点

只能包含静态成员

不能被实例化

·作用

1.将常用的静态成员写在静态类中 方便使用

2.静态类不能被实例化 更能体现工具类的唯一性

如Console就是一个静态类(控制工作台的工具)


2.静态构造函数

【一】概念

在构造函数前加上static修饰

【二】特点

【1】静态类和普通类都可以有

【2】不能使用访问修饰符

【3】不能有参数

【4】在使用类中的内容时,会自动调用一次

【三】作用

在静态构造函数中初识化静态变量

【四】使用

无论是静态类还是普通类

静态成员初始化


九.拓展方法


1.拓展方法的基本概念

· 概念

为现有 非静态变量类型 添加新方法

· 作用

【1】提升程序拓展性

【2】不需要在对象中重新写方法

【3】不需要继承来添加方法

【4】为别人封装的类写方法

· 特点

【1】一定是写在静态类中

【2】一定是个静态函数

【3】第一个参数为拓展目标

【4】第一个参数用this修饰


2.基本语法

访问修饰符 static 返回值 函数名 (this 拓展类名 参数名,参数类型 参数名,参数类型 参数名......)


3.实例

 static class Tools{//访问修饰符 static 返回值 函数名 (this 拓展类名 参数名,参数类型 参数名)//为int 扩展了一个成员方法//成员方法 是需要实例化对象后 才能使用的//value 代表使用该方法的 实例化对象public static void SpeakValue(this int value){//拓展方法逻辑Console.WriteLine("为int拓展方法"+value);}}
 public static void SpeakStringInfo (this string str,string str1,string str2 ){Console.WriteLine ("调用方法的对象" + str);Console.WriteLine("传的第一个参数" + str1);Console.WriteLine("传的第二个参数" + str2);}

4.使用

 int i = 10;i.SpeakValue();
            string str = "114514";str.SpeakStringInfo("1919","810");

运行结果

 


5.自定义类的拓展方法

自定义一个类

class test{int i = 10;public void Fun1(){Console.WriteLine("Fun1");}public void Fun2(){Console.WriteLine("Fun2");}        }

类拓展方法 

   public static void Fun3(this test t){Console.WriteLine("此为外部拓展的成员变量");}

 主函数

 test t = new test();t.Fun1();t.Fun2();t.Fun3();

运行结果 


十.运算符重载 *


1.基本概念

概念

让自己定义类和结构体 能够使用运算符

使用关键字 operator

特点

【1】一定是一个公共的静态方法

【2】返回值写在operater前

【3】逻辑处自定义

作用

让自定义类和结构体可以运算

注意

【1】条件运算符需要成对实现

【2】一个符号可以多个重载

【3】不能使用ref 和 out


2.基本语法

public static 返回类型 operator 运算符   ( 参数列表 )


3.实例

class point{public int x;public int y;public static point operator +(point p1, point p2){point p = new point();p.x = p1.x + p2.x;p.y = p1.y + p2.y;return p;}}

运算符可以多次重载

   class point{public int x;public int y;public static point operator +(point p1, point p2){point p = new point(0, 0);p.x = p1.x + p2.x;p.y = p1.y + p2.y;return p;}//构造函数public point(int x, int y){this.x = x;this.y = y;}public static point operator +(point p1, int value){point p = new point(0,0);p.x = p1.x + value;p.y = p1.y + value;return p;}}

 4.使用

  point p1 = new point(1,1);point p2 = new point(2,2);point p3 = p1 + p2;point p4 = p3 + 1; 

5.可重载和不可重载的运算符

·可重载

【1】算数运算符 + - * /

【2】逻辑运算符

【3】位运算符 

| 位或

& 位与

^ 异或

~ 取反(1个)

<<  左移

>>  右移

【4】条件运算符(成对出现)

>= <=    = !=   ><

·不可重载

逻辑与  &&   逻辑或   ||

索引符   [ ]

强转运算符  ()

特殊运算符 点 .  三目运算符? :  赋值符号=


十一.内部类和分布类


1.内部类

·概念

在一个类中再申明一个类

·特点

使用时要用包裹者点出自己

·注意

访问修饰符起重要作用


 class person{public int age;public string name;public class Body{Arm leftArm;Arm rightArm;class Arm{}}}

Arm如果没有public访问修饰符就无法在外部调用


2.分布类

·概念

把一个类分成几部分申明

·关键字

partial

·作用

分布描述一个类

增加程序的拓展性

·注意

分布类可以写在多个脚本文件中

分布类的访问修饰符要一致

分布类中不能有重复成员

 partial class Student{public int number;public bool sex;}partial class Student{public string name;}

虽然分开写了,但是二者是同一个类 

 在使用时可同时调用分布类的变量


3.分部方法

·概念

将方法的申明和实现分离

·特点

1.不能加访问修饰符

2.只能在分布类中申明

3.返回值只能是void

4.可以有参数但不用 out关键字

局限性大,了解即可

将方法的申明和实现分到了两个类中解决


C#面向对象三特性其一 封装

—— 完 ——


http://www.taodudu.cc/news/show-8381798.html

相关文章:

  • 【Unreal】小游戏Demo(头文件、宏以及API)-笔记六
  • [pygame] pygame设计联机对战桌游(三)
  • 英语语法语法检查网站推荐
  • Root就是手机的神经中枢
  • 携手搭建智慧城市“神经中枢”
  • 走近监控系统的神经中枢
  • 神经系统有哪些分类方式,神经系统分类介绍视频
  • 记一次在生产环境排查 OutOfMemoryError (OOM)的真实经历
  • java四层协议转发,Haproxy四层TCP转发到kubesphere k8s ingress获取真实客户端IP
  • Unity 获取真实旋转数据
  • yaf + smarty出现 Warning: Yaf_Loader::autoload(): Failed opening script... 问题
  • ES6笔记 13.正则方法、修饰符yus、UTF_16编码方式
  • Elasticsearch 7.1.1 安装 pinyin 分词器插件
  • 如何使用redis生成流水号 redis持久化
  • 使用java操作kafka订阅新增Topic踩坑
  • 论文阅读:MIL-VT: Multiple Instance LearningEnhanced Vision Transformer for FundusImage Classification
  • YUS框架之us指令前端
  • Yus框架之nl子级管控指令
  • YUS框架之uc颜色控制指令
  • 名画193 袁尚统《画选两幅》
  • Mac版python填色报错
  • Python画随机颜色的同心圆
  • 更改unity中Spine2D动画的颜色
  • python画圆填色_Python画koch曲线如何填充颜色
  • unity 绘画 游戏探索
  • python画三角形并涂色_怎么用python画三角形并填色?以及画五角星并且填色?(急!!!)...
  • svg图形与动画(0718)
  • CSS3 SVG创意文字线条填色动画js特效
  • 一生一芯4——使用星火应用商店在ubuntu下载QQ、微信、百度网盘
  • 解决宝塔面板无法下载软件和更新应用的问题