【C#补全计划:类和对象(六)—— 里氏替换原则】
一、is关键字
1. 概念:判断一个对象是否为指定类的对象
2. 返回值:布尔值。对象是指定类型的对象为true,不是为false
3. 使用:
语法:对象 is 类名
using System;namespace IsAsAndObject{ class Program { static void Main(string[] args) { // is关键字的使用 Ragdoll ragdoll = new Ragdoll(); bool isCat = ragdoll is Animal; // 使用is关键字检查ragdoll是否是Cat类型 bool isDog = ragdoll is Dog; // 检查ragdoll是否是Dog类型 Console.WriteLine(\"ragdoll是猫:\" + isCat); // 输出:True Console.WriteLine(\"ragdoll是狗:\" + isDog); // 输出:False } } class Animal { public string Name { get; set; } public void animalSpeak() { Console.WriteLine(\"Animal speaks\"); } } class Cat : Animal { public void catSpeak() { Console.WriteLine(\"Cat meows\"); } } class Dog : Animal { public void dogSpeak() { Console.WriteLine(\"Dog barks\"); } } class Ragdoll : Cat { public void ragdollSpeak() { Console.WriteLine(\"Ragdoll purrs\"); } }}
运行结果如下:
二、as关键字
1. 概念:将一个对象转换为指定类的对象
2. 返回值:指定类型的对象。对象转换成功返回指定类型对象,失败返回null
3. 使用:
语法:对象 as 类名
using System;namespace IsAsAndObject{ class Program { static void Main(string[] args) { // is关键字的使用 Ragdoll ragdoll = new Ragdoll(); bool isCat = ragdoll is Animal; // 使用is关键字检查ragdoll是否是Cat类型 bool isDog = ragdoll is Dog; // 检查ragdoll是否是Dog类型 Console.WriteLine(\"ragdoll是猫:\" + isCat); // 输出:True Console.WriteLine(\"ragdoll是狗:\" + isDog); // 输出:False // as关键字的使用 Animal dog = new Dog(); // 创建了一个Dog类实例,但将其引用赋给Animal类型的变量。编译时是Animal类型,运行时是Dog类型 // dog.dogSpeak() // 编译错误:Animal类没有dogSpeak方法 (dog as Dog).dogSpeak(); // 使用as关键字进行类型转换,调用Dog类的方法,编译成功 } } class Animal { public string Name { get; set; } public void animalSpeak() { Console.WriteLine(\"Animal speaks\"); } } class Cat : Animal { public void catSpeak() { Console.WriteLine(\"Cat meows\"); } } class Dog : Animal { public void dogSpeak() { Console.WriteLine(\"Dog barks\"); } } class Ragdoll : Cat { public void ragdollSpeak() { Console.WriteLine(\"Ragdoll purrs\"); } }}
运行结果如下:
三、里氏替换原则
里氏替换原则是面向对象七大原则中最重要的原则
1. 概念:任何父类出现的地方,子类都可以替代
2. 要求:
-
子类必须完全实现父类约定
-
子类不能破坏父类的行为
-
子类可以扩展但不能修改核心行为
3. 语法表现:父类容器装载子类对象,因为子类对象包含了父类中的所有内容
4. 作用:方便进行对象存储和管理
5. 示例:
using System;namespace IsAsAndObject{ class Program { static void Main(string[] args) { // is关键字的使用 Ragdoll ragdoll = new Ragdoll(); bool isCat = ragdoll is Animal; // 使用is关键字检查ragdoll是否是Cat类型 bool isDog = ragdoll is Dog; // 检查ragdoll是否是Dog类型 Console.WriteLine(\"ragdoll是猫:\" + isCat); // 输出:True Console.WriteLine(\"ragdoll是狗:\" + isDog); // 输出:False // as关键字的使用 Animal dog = new Dog(); // 创建了一个Dog类实例,但将其引用赋给Animal类型的变量。编译时是Animal类型,运行时是Dog类型 // dog.dogSpeak() // 编译错误:Animal类没有dogSpeak方法 (dog as Dog).dogSpeak(); // 使用as关键字进行类型转换,调用Dog类的方法,编译成功 // 里氏替换原则示例: Console.WriteLine(\"里氏替换原则示例:\"); Animal[] animals = new Animal[] { new Animal(\"小云\"), new Cat(\"小灰\"), new Dog(\"小黑\"), new Ragdoll(\"小白\") }; foreach(Animal a in animals) { Console.WriteLine(a.Name + \":\"); a.animalSpeak(); // 调用Animal类的方法,所有子类都可以调用 if (a is Cat) { // 使用is关键字检查是否是Cat类型 if(a is Ragdoll r) { // 进一步检查是否是Ragdoll类型 r.ragdollSpeak(); // 调用Ragdoll类的方法 continue; } (a as Cat).catSpeak(); // 调用Cat类的方法 } else if (a is Dog) {// 使用is关键字检查是否是Dog类型 (a as Dog).dogSpeak(); // 调用Dog类的方法 } } } } class Animal { public string Name { get; set; } public Animal() {} public Animal(string name) { Name = name; } public void animalSpeak() { Console.WriteLine(\"Animal speaks\"); } } class Cat : Animal { public Cat() {} public Cat(string name) : base(name) {} public void catSpeak() { Console.WriteLine(\"Cat meows\"); } } class Dog : Animal { public Dog() {} public Dog(string name) : base(name) {} public void dogSpeak() { Console.WriteLine(\"Dog barks\"); } } class Ragdoll : Cat { public Ragdoll() {} public Ragdoll(string name) : base(name) {} public void ragdollSpeak() { Console.WriteLine(\"Ragdoll purrs\"); } }}
运行结果如下:
四、万类之父:Object
1. 关键字:object
2. 概念:object是所有类的基类,他是一个类(引用类型)
3. 作用:
(1)可以利用里氏替换原则,用object容器装所有对象
(2)可以用来表示不确定的类型,作为函数参数中的类型
4. 使用:
using System;namespace IsAsAndObject{ class Program { static void Main(string[] args) { // is关键字的使用 Ragdoll ragdoll = new Ragdoll(); bool isCat = ragdoll is Animal; // 使用is关键字检查ragdoll是否是Cat类型 bool isDog = ragdoll is Dog; // 检查ragdoll是否是Dog类型 Console.WriteLine(\"ragdoll是猫:\" + isCat); // 输出:True Console.WriteLine(\"ragdoll是狗:\" + isDog); // 输出:False // as关键字的使用 Animal dog = new Dog(); // 创建了一个Dog类实例,但将其引用赋给Animal类型的变量。编译时是Animal类型,运行时是Dog类型 // dog.dogSpeak() // 编译错误:Animal类没有dogSpeak方法 (dog as Dog).dogSpeak(); // 使用as关键字进行类型转换,调用Dog类的方法,编译成功 // 里氏替换原则示例: Console.WriteLine(\"里氏替换原则示例:\"); Animal[] animals = new Animal[] { new Animal(\"小云\"), new Cat(\"小灰\"), new Dog(\"小黑\"), new Ragdoll(\"小白\") }; foreach(Animal a in animals) { Console.WriteLine(a.Name + \":\"); a.animalSpeak(); // 调用Animal类的方法,所有子类都可以调用 if (a is Cat) { // 使用is关键字检查是否是Cat类型 if(a is Ragdoll r) { // 进一步检查是否是Ragdoll类型 r.ragdollSpeak(); // 调用Ragdoll类的方法 continue; } (a as Cat).catSpeak(); // 调用Cat类的方法 } else if (a is Dog) {// 使用is关键字检查是否是Dog类型 (a as Dog).dogSpeak(); // 调用Dog类的方法 } } // 万类之父:Object的使用 // 引用类型 object obj1 = new Ragdoll(\"大白\"); if(obj1 is Ragdoll) (obj1 as Ragdoll).ragdollSpeak(); // 使用as关键字转换时,如果转换失败,结果为null // 值类型 object obj2 = 100; int i = (int)obj2; // 强制类型转换:将object类型转换为int类型 // 注意:如果obj2不是int类型,这里会抛出InvalidCastException异常 // 数组类型 object obj3 = new int[10]; int[] arr1 = obj3 as int[]; // 使用as关键字进行类型转换 int[] arr2 = (int[])obj3; // 强制类型转换 // string类型 object obj4 = \"Hello, World!\"; string str1 = obj4 as string; // 使用as关键字进行类型转换 string str2 = (string)obj4; // 强制类型转换 string str3 = obj4.ToString(); // 调用ToString方法转换 string str4 = obj4 + \"\"; // 使用字符串拼接转换 } } class Animal { public string Name { get; set; } public Animal() {} public Animal(string name) { Name = name; } public void animalSpeak() { Console.WriteLine(\"Animal speaks\"); } } class Cat : Animal { public Cat() {} public Cat(string name) : base(name) {} public void catSpeak() { Console.WriteLine(\"Cat meows\"); } } class Dog : Animal { public Dog() {} public Dog(string name) : base(name) {} public void dogSpeak() { Console.WriteLine(\"Dog barks\"); } } class Ragdoll : Cat { public Ragdoll() {} public Ragdoll(string name) : base(name) {} public void ragdollSpeak() { Console.WriteLine(\"Ragdoll purrs\"); } }}
五、装箱和拆箱
1. 概念:
(1)用object存储值类型(装箱)
(2)将object转换为值类型(拆箱)
2. 装箱:
(1)把值类型的变量用引用类型存储
(2)栈内存会迁移到堆内存中
3. 拆箱
(1)把引用类型存储的值类型取出来
(2)堆内存会迁移到栈内存中
4. 优点:不确定类型时可以方便参数的存储和传递
5. 缺点:存在内存迁移,增加性能消耗
using System;namespace IsAsAndObject{ class Program { static void Main(string[] args) { // is关键字的使用 Ragdoll ragdoll = new Ragdoll(); bool isCat = ragdoll is Animal; // 使用is关键字检查ragdoll是否是Cat类型 bool isDog = ragdoll is Dog; // 检查ragdoll是否是Dog类型 Console.WriteLine(\"ragdoll是猫:\" + isCat); // 输出:True Console.WriteLine(\"ragdoll是狗:\" + isDog); // 输出:False // as关键字的使用 Animal dog = new Dog(); // 创建了一个Dog类实例,但将其引用赋给Animal类型的变量。编译时是Animal类型,运行时是Dog类型 // dog.dogSpeak() // 编译错误:Animal类没有dogSpeak方法 (dog as Dog).dogSpeak(); // 使用as关键字进行类型转换,调用Dog类的方法,编译成功 // 里氏替换原则示例: Console.WriteLine(\"里氏替换原则示例:\"); Animal[] animals = new Animal[] { new Animal(\"小云\"), new Cat(\"小灰\"), new Dog(\"小黑\"), new Ragdoll(\"小白\") }; foreach(Animal a in animals) { Console.WriteLine(a.Name + \":\"); a.animalSpeak(); // 调用Animal类的方法,所有子类都可以调用 if (a is Cat) { // 使用is关键字检查是否是Cat类型 if(a is Ragdoll r) { // 进一步检查是否是Ragdoll类型 r.ragdollSpeak(); // 调用Ragdoll类的方法 continue; } (a as Cat).catSpeak(); // 调用Cat类的方法 } else if (a is Dog) {// 使用is关键字检查是否是Dog类型 (a as Dog).dogSpeak(); // 调用Dog类的方法 } } // 万类之父:Object的使用 // 引用类型 object obj1 = new Ragdoll(\"大白\"); if(obj1 is Ragdoll) (obj1 as Ragdoll).ragdollSpeak(); // 使用as关键字转换时,如果转换失败,结果为null // 值类型 object obj2 = 100; int i = (int)obj2; // 强制类型转换:将object类型转换为int类型 // 注意:如果obj2不是int类型,这里会抛出InvalidCastException异常 // 数组类型 object obj3 = new int[10]; int[] arr1 = obj3 as int[]; // 使用as关键字进行类型转换 int[] arr2 = (int[])obj3; // 强制类型转换 // string类型 object obj4 = \"Hello, World!\"; string str1 = obj4 as string; // 使用as关键字进行类型转换 string str2 = (string)obj4; // 强制类型转换 string str3 = obj4.ToString(); // 调用ToString方法转换 string str4 = obj4 + \"\"; // 使用字符串拼接转换 // 装箱和拆箱 Console.WriteLine(\"装箱和拆箱示例:\"); Console.WriteLine(\"sum = \" + Sum(1, 2.0, 3.0f, \"4\", new Dog())); // 装箱操作:将不确定类型的值转换为object类型 } static float Sum(params object[] objects) { float sum = 0; foreach (object o in objects) // 拆箱操作:将object类型的值转换为具体类型 { if(o is int) sum += (int)o; if(o is float) sum += (float)o; if(o is double) sum += (float)(double)o; if(o is string) sum += float.TryParse((string)o, out float result) ? result : 0f; if(o is Animal) continue; } return sum; } } class Animal { public string Name { get; set; } public Animal() {} public Animal(string name) { Name = name; } public void animalSpeak() { Console.WriteLine(\"Animal speaks\"); } } class Cat : Animal { public Cat() {} public Cat(string name) : base(name) {} public void catSpeak() { Console.WriteLine(\"Cat meows\"); } } class Dog : Animal { public Dog() {} public Dog(string name) : base(name) {} public void dogSpeak() { Console.WriteLine(\"Dog barks\"); } } class Ragdoll : Cat { public Ragdoll() {} public Ragdoll(string name) : base(name) {} public void ragdollSpeak() { Console.WriteLine(\"Ragdoll purrs\"); } }}
运行结果如下:
今天的学习就到这里了。感谢阅读。
再见!