- A+
一 类继承
继承是使代码可以复用的重要手段,也是面向对象程序设计的核心思想之一。继承呈现了面向对象程序设计的层次结构。
通过继承,我们能以一个已经存在的类为基础来定义一个新类。已存在的类称为基类或父类,新类称为派生类或子类。
派生类的成员包括:基类的成员和派生类自身声明的成员。
继承自基类的成员可以被访问,就像是派生类自己声明的一样。
class BaseClass { public string BaseField = "BaseField"; public void BaseMethod(string str) { Console.WriteLine($"BaseWrite:{str}"); } } class DerivedClass : BaseClass { public string DerivedField = "DerivedField"; public void DerivedMethod(string str) { Console.WriteLine($"DerivedWrite:{str}"); } } class Program { static void Main() { //派生类可以访问基类的成员 var derived = new DerivedClass(); derived.BaseMethod(derived.BaseField); derived.BaseMethod(derived.DerivedField); derived.DerivedMethod(derived.BaseField); derived.DerivedMethod(derived.DerivedField); } }
二 所有类都派生自object类
除了object类,所有的类都是派生类,没有基类规格说明的类隐式地派生自object类。
object类是唯一的非派生类,因为它是继承层次结构的基础。
C#的类是单继承,一个类只能直接继承一个基类,而一个基类可以有多个派生类。
类继承的层次没有限制,作为基类的类A可以派生自类B,而这个类B又派生自类C,一直下去,直至object类。
三 屏蔽基类的成员
派生类不能删除基类的成员,但可以使用new关键字修饰基类成员名称相同的成员来屏蔽基类成员。
如果派生类需要访问被屏蔽的基类成员,可以使用base.表达式,实现基类访问。
从程序设计角度,应尽量避免使用基类访问这一特性。
class BaseClass { public string BaseField = "BaseField"; } class DerivedClass : BaseClass { new public string BaseField = "NewBaseField"; //屏蔽基类成员 public void Show() { Console.WriteLine(BaseField); //输出NewBaseField Console.WriteLine(base.BaseField); //输出BaseField } } class Program { static void Main() { var derived = new DerivedClass(); derived.Show(); } }
四 使用基类的引用
4.1 派生类的实例可以转换成基类的实例
关于里式转换:
- 子类可以赋值给父类
- 如果一个父类对象中装的是子类对象,则可以将这个父类对象强制转换为子类对象。
派生类的实例由基类的实例加上派生类新增的成员组成。派生类的引用指向整个类对象。
如果有一个派生类对象的引用,就可以通过转换获取基类部分的引用。
class MyBaseClass { public void Print() { Console.WriteLine("This is the base class"); } } class MyDerivedClass : MyBaseClass { new public void Print() { Console.WriteLine("This is the derivedclass"); } } class Program { static void Main() { MyDerivedClass derived = new MyDerivedClass(); MyBaseClass mybc = (MyBaseClass)derived; //转换成基类 derived.Print(); // This is the derivedclass mybc.Print(); // This is the base class } }
4.2 虚方法和覆写方法
虚方法可以是基类的引用访问升至派生类中。
使用基类引用调用派生类的方法需要满足:
- 派生类的方法和基类的方法具有相同的签名和返回类型;
- 基类方法使用virtual标注;
- 派生类方法使用override标注;
属性、事件和索引器也可以使用virtual-override
class MyBaseClass { virtual public void Print() { Console.WriteLine("This is the base class"); } } class MyDerivedClass : MyBaseClass { override public void Print() { Console.WriteLine("This is the derivedclass"); } } class Program { static void Main() { MyDerivedClass derived = new MyDerivedClass(); MyBaseClass mybc = (MyBaseClass)derived; //转换成基类 derived.Print(); // This is the derivedclass mybc.Print(); // This is the derivedclass //对基类方法的调用实际上调用了派生类中的方法 } }
五 构造函数的执行
要创建对象的基类部分,需要隐式地调用基类的某个构造函数;
继承层次链中的每个类在执行它自己的构造函数前执行它的基类构造函数。
5.1 构造函数初始化语句
使用关键字base指明使用哪一个基类构造函数。
使用关键字this指明使用当前类的哪个构造函数。
public MyDerivedClass(int x,string s):base(s,x) ... ------------ public MyDerivedClass(int x):this(s,"default string") ...
六 类访问修饰符
类的可访问性有两个级别:
- public : 可以被系统内任何程序集中的代码访问
- internal : 只能被它自己所在程序集内的类访问