ToB企服应用市场:ToB评测及商务社交产业平台

标题: C#面向对象核心-封装 [打印本页]

作者: 郭卫东    时间: 2023-4-4 14:21
标题: C#面向对象核心-封装
封装

封装定义为"把一个或多个项目封闭在一个物理的或者逻辑的包中",这个包就是类。在面向对象程序设计方法论中,封装可以防止对实现细节的访问。
1 类和对象

1.1 什么是类

具有相同特征、行为,是一类事物的抽象
类是对象的模板,通过类创建对象
1.2 类声明语法
  1. //声明在namespace中
  2. /*class 类名
  3. {
  4.     //成员变量 表示特征
  5.     //成员方法 表示行为
  6.     //成员属性 保护成员变量
  7.     //构造函数和析构函数 初始化和释放
  8.     //索引器 像数组一样使用
  9.     //运算符重载 自定义对象可计算
  10.     //静态成员 类名.点出成员使用
  11. }*/
  12. class Person
  13. {
  14. }
复制代码
1.3 类对象

类声明和类对象声明是两个概念:
  1. //类名 变量名;
  2. //类名 变量名 = null;
  3. //类名 变量名 = new 类名();
  4. Person p1;
  5. Person p2 = null;//空,不分配堆的内存空间
  6. //p3 p4虽然来自一个类的实例化对象,但它们的特征行为等都是分别独有的,不会相互共享
  7. Person p3 = new Person();
  8. Person p4 = new Person();
复制代码
2 成员变量和访问修饰符

2.1 成员变量

声明在类语句块中,来描述对象的特征,可以是任意的变量类型,数量无限制,是否赋值根据需求确定
  1. enum E_SexType
  2. {
  3.     Man,
  4.     Woman,
  5. }
  6. struct Position
  7. {
  8. }
  9. class Pet//宠物类
  10. {
  11. }
  12. class Person
  13. {
  14.     //成员变量
  15.     public string name;
  16.     public int age;
  17.     public E_SexType sex;
  18.     //如果在类中声明和自己类型相同的成员变量时,不能对它实例化:Person grilFriend = new Person();
  19.     public Person grilFriend;//女朋友 类可以用自己,但结构体不能,因为类在初始化时候才会分配内存,结构体则会一直死循环
  20.     public Person[] friend;//朋友
  21.     public Position pos;//位置
  22.     public Pet pet = new Pet();//宠物
  23. }
复制代码
2.2 访问修饰符

2.3 成员变量的使用和初始值
  1. Person p = new Person();
  2. /* 成员变量的使用和初始值
  3. * 值类型、数字类型:默认为0
  4. * bool类型:默认为false
  5. * 引用类型:默认为null
  6. * 用default(变量类型) 关键字可以看默认值
  7. */
  8. Console.WriteLine(default(bool));
  9. p.age = 10;
复制代码
3 成员方法

3.1 成员方法声明

  1. class Person
  2. {
  3.     public string name;
  4.     public int age;
  5.     public Person[] friends;
  6.     //成员方法
  7.     public void Speak(string str)
  8.     {
  9.         Console.WriteLine($"{name}说{str}");
  10.     }
  11.     public bool isAudlt()
  12.     {
  13.         return age >= 18;
  14.     }
  15.     public void AddFriend(Person p)//添加朋友
  16.     {
  17.         if (friends == null)
  18.         {
  19.             friends = new Person[] { p };
  20.         }
  21.         else
  22.         {
  23.             Person[] newFriends = new Person[friends.Length + 1];
  24.             for(int i = 0; i < friends.Length; i++)//老朋友复制到新数组
  25.             {
  26.                 newFriends[i] = friends[i];
  27.             }
  28.             newFriends[newFriends.Length - 1] = p;//新加的朋友
  29.             friends = newFriends;//地址重定向
  30.         }
  31.     }
复制代码
3.2 成员方法的使用

必须实例化对象,再通过对象来使用,相当于对象执行了某个行为
  1. Person p =  new Person();
  2. p.name = "abc";
  3. p.age = 18;
  4. p.Speak("123");
  5. if (p.isAudlt()) p.Speak("我成年了");//使用
  6. Person p2 = new Person();
  7. p2.name = "def";
  8. p2.age = 24;
  9. p.AddFriend(p2);
  10. foreach(Person f in p.friends)
  11. {
  12.     Console.WriteLine(f.name);
  13. }
复制代码
4 构造函数、析构函数和垃圾回收

4.1 构造函数

  1. class Person
  2. {
  3.     public string name;
  4.     public int age;
  5.     //类中允许无参构造函数,结构体中不行
  6.     //无参构造函数
  7.     public Person()
  8.     {
  9.         name = "tyy";
  10.         age = 24;
  11.     }
  12.     //构造函数可以被重载,this代表当前调用该函数的对象本身
  13.     public Person(string name, int age)
  14.     {
  15.         this.name = name;
  16.         this.age = age;
  17.     }
  18.     //构造函数特殊写法:通过this 复用构造函数代码
  19.     //访问修饰符 构造函数名(参数):this(参数1,参数2...)。先调用this()里面的构造函数重载,再执行后面花括号内容
  20.     //先调用this()里面的构造函数重载,再执行后面花括号内容
  21.     public Person(string name):this()
  22.     {
  23.         Console.WriteLine("两个构造函数调用");
  24.     }
  25. }
复制代码
4.2 析构函数

  1. class Person
  2. {
  3.     public Person()
  4.     {
  5.         
  6.     }
  7.         ~Person()
  8.     {
  9.     }
  10. }
复制代码
4.3 垃圾回收

GC基本原理:
  1. //手动出发垃圾回收的方法,一般在Loading切换场景时才调用
  2. GC.Collect();
复制代码
5 成员属性

5.1 成员属性的基本语法
  1. /*
  2. 访问修饰符 属性类型 属性名
  3. {
  4.     get{}   读,写了get就一定要有一个返回值
  5.     set{}   写
  6. }
  7. */
  8. class Person
  9. {
  10.     private string name;
  11.     private int age;
  12.     private int money;
  13.     private bool sex;
  14.     //属性的命名用帕斯卡命名法
  15.     public string Name
  16.     {
  17.         get
  18.         {
  19.             //可以在返回之前添加一些逻辑条件
  20.             return name;//虽然name是私有的,但是通过成员属性也能得到它
  21.         }
  22.         set
  23.         {
  24.             //可以在设置之前添加一些逻辑条件
  25.             //value关键字表示外部传入的值
  26.             name = value;
  27.         }
  28.     }
  29.     public int Money
  30.     {
  31.         get
  32.         {
  33.             //解密处理
  34.             return money - 5;
  35.         }
  36.         set
  37.         {
  38.             //可以进行额外的加密处理 起到安全和保密作用
  39.             if(value < 0)
  40.             {
  41.                 value = 0;
  42.                 Console.WriteLine("钱不能为负数");
  43.             }
  44.             money = value + 5;
  45.         }
  46.     }
  47. }
复制代码
5.2 成员属性的使用
  1. Person p = new Person();
  2. p.Name = "abc";//执行set{}
  3. Console.WriteLine(p.Name);//p.Name执行get{}
  4. p.Money = 1000;
  5. Console.WriteLine(p.Money);//外部看是1000元,但在内存里面是1005元 起到了加密的作用
复制代码
5.3 get和set的访问修饰符

5.4 get和set可以只有一个
  1. class Person
  2. {
  3.     private string name;
  4.     private int age;
  5.     private int money;
  6.     private bool sex;
  7.    
  8.     public bool Sex
  9.     {
  10.         get { return sex; }//创造只读属性,private类型的成员也能读
  11.     }
  12. }
复制代码
5.5 自动属性

  1. class Person
  2. {
  3.     private string name;
  4.     private int age;
  5.     private int money;
  6.     private bool sex;
  7.    
  8.     public float Height
  9.     {
  10.         get;
  11.         private set;
  12.     }
  13. }
复制代码
6 索引器

6.1 基本语法
  1. /*
  2. element-type this[int index]
  3. {
  4.     // get 访问器
  5.     get
  6.     {
  7.         // 返回 index 指定的值
  8.     }
  9.     // set 访问器
  10.     set
  11.     {
  12.         // 设置 index 指定的值
  13.     }
  14. }
  15. */
  16. class Person
  17. {
  18.     private string name;
  19.     private int age;
  20.     private Person[] friends;
  21.     public Person this[int index]
  22.     {
  23.         //可以写逻辑条件来处理
  24.         get
  25.         {
  26.             if(friends == null || friends.Length - 1 < index)
  27.             {
  28.                 return null;
  29.             }
  30.             return friends[index];
  31.         }
  32.         set
  33.         {
  34.             //和成员属性类似,value代表传入的值
  35.             if(friends == null)
  36.             {
  37.                 friends = new Person[] { value };
  38.             }else if(index > friends.Length - 1)
  39.             {
  40.                 friends[friends.Length - 1] = value;//举例 如果索引越界就把最后一个朋友顶掉
  41.             }
  42.             else friends[index] = value;
  43.         }
  44.     }
  45. }
复制代码
6.2 使用
  1. Person p = new Person();
  2. p[0] = new Person();//调用set 得到1个朋友
  3. Console.WriteLine(p[0]);//调用get
复制代码
6.3 索引器重载
  1. class Person
  2. {
  3.     public int[,] array;
  4.    
  5.     //函数名相同,但参数类型、个数或顺序不同
  6.     public int this[int i, int j]
  7.     {
  8.         get
  9.         {
  10.             return array[i, j];
  11.         }
  12.         set
  13.         {
  14.             array[i, j] = value;
  15.         }
  16.     }
  17. }
复制代码
7 静态成员

7.1 自定义静态成员
  1. class Test
  2. {
  3.     //静态成员变量
  4.     public static float PI = 3.121592654f;
  5.     //成员变量
  6.     public int testInt = 100;
  7.     //静态成员方法
  8.     //静态方法不能使用非静态成员变量,与静态和非静态的生命周期有关
  9.     public static float CalcCircle(float r)
  10.     {
  11.         //πr²
  12.         return PI * r * r;
  13.     }
  14.     //普通成员方法
  15.     //非静态方法可以使用静态成员变量
  16.     public void testFun()
  17.     {
  18.         Console.WriteLine("123");
  19.         Console.WriteLine(PI);
  20.     }
  21. }
复制代码
7.2 静态成员使用
  1. Console.WriteLine(Test.PI);
  2. Console.WriteLine(Test.CalcCircle(2));
  3. //普通的只有new了对象之后才能使用那些变量方法等
  4. Test t = new Test();
  5. Console.WriteLine(t.testInt);
  6. t.testFun();
复制代码
7.3 为什么能够不实例化对象直接使用

7.4 常量const和静态变量static

相同点:都可以使用类名+点使用
不同点:
8 静态类和静态构造函数

8.1 静态类

用 static 修饰的类,只能包含静态成员,不能被实例化
作用:
  1. static class TestClass
  2. {
  3.     public static int testIndex = 0;
  4.     public static void testFun()
  5.     {
  6.     }
  7. }
复制代码
8.2 静态构造函数

8.2.1 静态类 中的 静态构造函数
  1. static class StaticClass
  2. {
  3.     //第一次使用类时,类里面的静态成员自动调用一次
  4.     public static int testInt = 100;
  5.     public static int testInt2 = 100;
  6.     static StaticClass()
  7.     {
  8.         Console.WriteLine("静态构造函数");
  9.     }
  10. }
复制代码
8.2.2 普通类 中的 静态构造函数
  1. class Test
  2. {
  3.     public static int testInt = 200;
  4.     static Test()
  5.     {
  6.         Console.WriteLine("静态构造");
  7.     }
  8.     public Test()
  9.     {
  10.         Console.WriteLine("普通构造");
  11.     }
  12. }
复制代码
8.3 使用
  1. Console.WriteLine(StaticClass.testInt);
  2. //第一次使用类时,类里面的静态成员自动调用一次
  3. Console.WriteLine(Test.testInt);
  4. //普通构造在new的时候调用
  5. Test t = new Test();
复制代码
9 拓展方法

为现有 非静态 的  添加新方法
作用:
特点:
9.1 基本语法

访问修饰符 static 返回值 函数名(this 要拓展的类名 参数名,参数类型 参数名,......)
  1. static class Tools
  2. {
  3.     //为int拓展了一个成员方法,int里面是没有SpeakValue方法的
  4.     //value 代表使用该方法的 实例化对象
  5.     public static void SpeakValue(this int value)
  6.     {
  7.         //拓展方法的逻辑
  8.         Console.WriteLine("为int拓展的方法" + value);
  9.     }
  10.     public static void SpeakStringInfo(this string str, string str2, string str3)
  11.     {
  12.         Console.WriteLine("为string拓展的方法,调用方法的对象是:" + str);
  13.         Console.WriteLine("传的参数:" + str2 + str3);
  14.     }
  15.     //为自定义的类型Test拓展方法
  16.     public static void Fun3(this Test t)
  17.     {
  18.         Console.WriteLine("为Test拓展的方法");
  19.     }
  20. }
  21. class Test
  22. {
  23.     public int i = 10;
  24.     public void Fun1()
  25.     {
  26.         Console.WriteLine("123");
  27.     }
  28.     public void Fun2()
  29.     {
  30.         Console.WriteLine("456");
  31.     }
  32. }
复制代码
9.2 使用
  1. int i = 10;
  2. i.SpeakValue();
  3. string s = "ABC";
  4. s.SpeakStringInfo("a ", "b");
  5. Test t = new Test();
  6. t.Fun3();
复制代码
10 运算符重载

10.1 基本概念

作用:让自定义的类和结构体能够使用运算符进行运算,关键字 operator
特点:
注意:
10.2 可重载和不可重载的运算符

注意:运算符需要两个参数还是一个参数
可重载的:
<ul>算数运算符:+ - * / % ++ --
逻辑运算符:!
位运算符:| & ^ ~ >
条件运算符:> < >=




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4