翼度科技»论坛 编程开发 .net 查看内容

C#面向对象核心-继承

8

主题

8

帖子

24

积分

新手上路

Rank: 1

积分
24
继承

继承主要实现重用代码,来节省开发时间。
1 继承基本概念

一个类B继承一个类A,被继承的类A称为 父类、基类、超类,继承的类B称为 子类、派生类。

  • 子类会继承父类的所有成员
  • 子类拥有父类的所有特征和行为
  • 子类可以有自己的特征行为
  • C#中允许子类和父类存在同名的成员,但不建议使用
特点:

  • 单根性 子类只能有一个父类,不能多继承
  • 传递性 子类可以间接继承父类的父类
1.1 基本语法
  1. class Teacher
  2. {
  3.     public string name;
  4.     public int number;
  5.     public void SpeakName()
  6.     {
  7.         Console.WriteLine(name);
  8.     }
  9. }
  10. class TeachingTeacher : Teacher
  11. {
  12.     public string subject;//科目
  13.     public void SpeakSubject()
  14.     {
  15.         Console.WriteLine($"我是{subject}老师");
  16.     }
  17. }
  18. class ChineseTeacher : TeachingTeacher
  19. {
  20.     public void Skill()
  21.     {
  22.         Console.WriteLine("余幼时即嗜学");
  23.     }
  24. }
复制代码
1.2 使用
  1. TeachingTeacher tt = new TeachingTeacher();
  2. tt.name = "abc";
  3. tt.number = 1;
  4. tt.SpeakName();
  5. tt.subject = "C#";
  6. tt.SpeakSubject();
  7. ChineseTeacher ct = new ChineseTeacher();
  8. ct.name = "def";
  9. ct.number = 2;
  10. ct.SpeakName();
  11. ct.subject = "Chinese";
  12. ct.SpeakSubject();
  13. ct.Skill();
复制代码
2 里氏替换原则

里氏替换原则(Liskov Substitution principle):子类可以扩展父类的功能,但不能改变父类原有的功能,是面向对象七大原则中最重要的原则。
概念:任何父类出现的地方,子类都可以替代
重点:语法表现一父类容器装子类对象,因为子类对象包含了父类的所有内容
作用:方便进行对象存储和管理
2.1 基本语法
  1. class GameObject
  2. {
  3. }
  4. class Player : GameObject
  5. {
  6.     public void PlayerAttack()
  7.     {
  8.         Console.WriteLine("玩家攻击");
  9.     }
  10. }
  11. class Monster : GameObject
  12. {
  13.     public void MonsterAttack()
  14.     {
  15.         Console.WriteLine("怪物攻击");
  16.     }
  17. }
  18. class Boss : GameObject
  19. {
  20.     public void BossAttack()
  21.     {
  22.         Console.WriteLine("Boss攻击");
  23.     }
  24. }
  25. //Main
  26. //里氏替换原则 用父类容器装载子类对象
  27. GameObject p = new Player();
  28. GameObject m = new Monster();
  29. GameObject b = new Boss();
复制代码
2.2 is 和 as

is:判断一个对象是否为指定对象,返回:bool,是为真,不是为假
as:将一个对象转换为指定类对象,返回:成功返回指定类对象,失败返回null
基本语法:

  • 类对象 is 类名,语句返回真或假
  • 类对象 as 类名,语句返回对象或null
  1. if(p is Player)
  2. {
  3.     Player p1 = p as Player;
  4.     p1.PlayerAttack();
  5. }
复制代码
3 继承的构造函数

3.1 基本概念

子类声明子类对象时,先执行父类的构造函数,再执行子类的构造函数。

  • 父类的无参构造很重要,有参构造函数会自动顶掉无参构造函数,若写了有参构造,则最好还要写无参构造
  • 子类可以通过base关键字代表父类调用父类构造函数
  • 构造函数执行顺序:父类的父类的构造函数——父类的构造函数——子类的构造函数
  1. class GameObject
  2. {
  3.     public GameObject()
  4.     {
  5.         Console.WriteLine("GameObject的构造函数");
  6.     }
  7. }
  8. class Player : GameObject
  9. {
  10.     public Player()
  11.     {
  12.         Console.WriteLine("Player的构造函数");
  13.     }
  14. }
  15. class MainPlayer : Player
  16. {
  17.     public MainPlayer()
  18.     {
  19.         Console.WriteLine("MainPlayer的构造函数");
  20.     }
  21. }
  22. //Main
  23. MainPlayer mp = new MainPlayer();
  24. /*
  25. 输出:
  26. GameObject的构造函数
  27. Player的构造函数
  28. MainPlayer的构造函数
  29. */
  30. Father构造
  31. Son一个参数构造
  32. Son两个个参数构造
复制代码
3.2 base关键字

通过 base(参数) 可以调用指定父类构造。
  1. class Father
  2. {
  3.     /*public Father()
  4.     {
  5.     }*/
  6.     public Father(int i)//有参构造函数会自动顶掉无参构造函数
  7.     {
  8.         Console.WriteLine("Father构造");
  9.     }
  10. }
  11. //子类实例化时默认先调用父类的无参构造,如果父类无参构造被顶掉,就会报错
  12. class Son : Father
  13. {
  14.     //通过base改变默认调用父类的无参构造,指定为有参构造
  15.     public Son(int i) : base(i)
  16.     {
  17.         Console.WriteLine("Son一个参数构造");
  18.     }
  19.     public Son(int i, string str) : this(i)//this(i)表示调用一个参数的构造函数public Son(int i) : base(i){}
  20.     {
  21.         Console.WriteLine("Son两个个参数构造");
  22.     }
  23. }
  24. //Main
  25. Son s = new Son(1, "123");
  26. /*
  27. 输出:
  28. Father构造
  29. Son一个参数构造
  30. Son两个个参数构造
  31. */
复制代码
4 object 和装箱拆箱

4.1 object

object 是所有类型的父类,它是一个类(引用类型)。
作用:

  • 利用里氏替换原则,用object容器装所有对象
  • 表示不确定类型,作为函数参数类型
4.2 使用
  1. class Father
  2. {
  3. }
  4. class Son : Father
  5. {
  6.     public void Speak()
  7.     {
  8.     }
  9. }
  10. //Main
  11. Father f = new Son();//用父类容器装载子类
  12. if(f is Son)
  13. {
  14.     (f as Son).Speak();
  15. }
  16. //用object装载万物,然后转换成所需类型来使用
  17. //1、引用类型
  18. object o = new Son();
  19. //用is和as来判断和转换即可
  20. if(o is Son)
  21. {
  22.     (o as Son).Speak();
  23. }
  24. //2、值类型
  25. object o2 = 1f;
  26. //用强转
  27. float fl = (float)o2;
  28. //特殊string类型
  29. object str = "123";
  30. string str2 = str as string;
  31. //数组
  32. object arr = new int[10];
  33. int[] ar = arr as int[];
复制代码
4.3 装箱和拆箱


  • 装箱:用object来存值类型,即值类型转换为object类型 ,栈内存会迁移到堆内存中
  • 拆箱:再把object转为值类型 ,堆内存会迁移到栈内存中
  • 好处:不确定类型时可以方便参数的存储和传递
  • 坏处:存在内存迁移,增加性能消耗
  1. object v = 3;//装箱
  2. int a = (int)v;//拆箱
复制代码
5 sealed 密封类


  • 使用 sealed 关键字修饰的类,让类无法被继承
  • 在面向对象程序的设计中,密封类的主要作用就是不允许最底层子类被继承,可以保证程序的规范性、安全性
  1. sealed class Father
  2. {
  3. }
  4. class Son : Father//报错,无法继承
  5. {
  6. }
复制代码
来源:https://www.cnblogs.com/tanyuyang/archive/2023/03/28/17265952.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具