[C#基本程序结构Ⅲ]继承
继承
继承,能够定义可重用、扩展或修改父类行为的子类。 成员被继承的类称为基类。 继承基类成员的类称为派生类。
//基类 namespace ConsoleApp1 { class BaseClass { public int data1; public string data2; public void BaseClassFunction1() { Console.WriteLine("BaseClass:Function1"); } public void BaseClassFunction2() { Console.WriteLine("BaseClass:Function2"); } } }
//派生类1 namespace ConsoleApp1 { class DrivedClass1 : BaseClass { } }
//派生类2 namespace ConsoleApp1 { class DrivedClass2 : BaseClass { public int data3; public void DrivedClass2Function1() { Console.WriteLine("DrivedClass2:Function"); } } }
//主程序 using ConsoleApp1; namespace DEMO { class Program { static void Main(string[] args) { BaseClass bc = new BaseClass(); bc.data1 = 34; bc.data2 = "abcde"; Console.WriteLine(bc.data1); Console.WriteLine(bc.data2); bc.BaseClassFunction1(); bc.BaseClassFunction2(); //派生类可以使用基类的类成员 DrivedClass1 dc1 = new DrivedClass1(); dc1.data1 = 1; dc1.data2 = "12345"; Console.WriteLine(dc1.data1); Console.WriteLine(dc1.data2); dc1.BaseClassFunction1(); dc1.BaseClassFunction2(); //派生类可以有自己新的类成员 DrivedClass2 dc2 = new DrivedClass2(); dc2.DrivedClass2Function1(); } } }
继承-this&base
①this可以访问当前类中定义的字段,属性和⽅法(有没有this都可以访问),有this可以让编译器给出提⽰,另外当⽅法的参数跟字段重名的时候,使⽤this可以表明访问的是类中的字段
②base可以调⽤⽗类中的公有⽅法和字段(有没有base都可以访问),但是加上base可以让编译器给出提⽰,把所有可以调⽤的字段和⽅法罗列出来⽅便选择
//基类 using System.Runtime.CompilerServices; namespace ConsoleApp1 { class BaseClass { public int data1; public string data2; public void BaseClassFunction1() { Console.WriteLine("BaseClass:Function1"); } public void BaseClassFunction2() { Console.WriteLine("BaseClass:Function2"); } } }
//派生类1 namespace ConsoleApp1 { class DrivedClass1 : BaseClass { } }
//派生类2 namespace ConsoleApp1 { class DrivedClass2 : BaseClass { public int data3; public void DrivedClass2Function1() { Console.WriteLine("DrivedClass2:Function"); } public void DrivedClass2Function2() { this.BaseClassFunction1(); this.BaseClassFunction2(); this.DrivedClass2Function1(); base.BaseClassFunction1(); base.data1 = 2; } } }
//主程序 using ConsoleApp1; namespace DEMO { class Program { static void Main(string[] args) { BaseClass bc = new BaseClass(); bc.data1 = 34; bc.data2 = "abcde"; Console.WriteLine(bc.data1); Console.WriteLine(bc.data2); bc.BaseClassFunction1(); bc.BaseClassFunction2(); //派生类可以使用基类的类成员 DrivedClass1 dc1 = new DrivedClass1(); dc1.data1 = 1; dc1.data2 = "12345"; Console.WriteLine(dc1.data1); Console.WriteLine(dc1.data2); dc1.BaseClassFunction1(); dc1.BaseClassFunction2(); //派生类可以有自己新的类成员 DrivedClass2 dc2 = new DrivedClass2(); dc2.DrivedClass2Function1(); dc2.DrivedClass2Function2(); } } }
①派生类可以通过提供重写实现代码来重写继承的成员,基类成员必须标记有 virtual 关键字,才能重写继承的成员
②在派⽣类中重写另外⼀个函数时,要使⽤override关键字显⽰声明
③在⼦类⾥⾯重写虚函数之后,不管在哪⾥调⽤都是调⽤重写之后的⽅法
//基类 using System.Runtime.CompilerServices; namespace ConsoleApp1 { class MyBaseClass { public virtual string VirtualMethod() { return "Method is called in base class"; } } }
//派生类1 namespace ConsoleApp1 { class MyDerivedClass : MyBaseClass { public override string VirtualMethod() { return "Method is called in derivedclass."; } } }
继承-abstract&override
①使⽤abstract修饰的类为抽象类,抽象类只能是其他类的基类,不能与sealed、static⼀起使⽤
②abstract可以修饰抽象类中的⽅法或属性,该⽅法或属性不能包含实现,且访问级别不能为私有
③抽象类不能被实例化
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1 { //抽象类 public abstract class Class1 { private int intData0; private int intData1; public void Function0() { Console.WriteLine("Function0"); } //抽象类将不能声明主体 public abstract void AbsClass(); } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1 { //抽象类的实现 public class Class2 : Class1 { public override void AbsClass() { Console.WriteLine("抽象类的实现"); } } }
namespace ConsoleApp1 { internal class Program { static void Main(string[] args) { Console.WriteLine("Hello, World!"); //Class1 class1 = new Class1(); //cs0144 Class2 class2 = new Class2(); class2.Function0(); class2.AbsClass(); Console.ReadKey(); } } }
继承-sealed
C#允许把类和⽅法声明为sealed
将类声明为密封类,则不能继承该类;
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1 { //密封类 public sealed class Class1 { private int intData0; private int intData1; public void SeaClass() { Console.WriteLine("密封类的实现"); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; //将类声明为密封类,则不能继承该类 namespace ConsoleApp1 { //CS0509无法从密封类派生 public class Class2 : Class1 { } }
namespace ConsoleApp1 { internal class Program { static void Main(string[] args) { Console.WriteLine("Hello, World!"); Class1 class1 = new Class1(); class1.SeaClass(); Console.ReadKey(); } } }
将⽅法声明为密封方法,则不能重写该⽅法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1 { public class Class1 { private int intData0; private int intData1; public virtual void SeaClass() { Console.WriteLine("密封类的实现"); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1 { public class Class2 : Class1 { public sealed override void SeaClass() { Console.WriteLine("派生类的实现"); } } public class Class3 : Class2 { public override void SeaClass()//CS0239 "Class3.SeaClass()": 继承成员"Class2.SeaClass()"是密封的,无法进行重写 { Console.WriteLine("1"); } } }
namespace ConsoleApp1 { internal class Program { static void Main(string[] args) { Console.WriteLine("Hello, World!"); Class1 class1 = new Class1(); class1.SeaClass(); Class2 class2 = new Class2(); class2.SeaClass(); Console.ReadKey(); } } }