继承
隐藏基类成员
public:该成员能够被子类继承,并且能在类的定义之外被访问
protected:该成员能被被子类继承,但不能在类定义之外被访问
private:该成员不能被子类继承,也不能在类定义之外被访问
子类的构造函数
基类的构造函数通常是public的,但派生类并不继承基类的构造函数
派生类有自己的构造函数,负责初始化派生类中信定义的成员。如果成员是从基类继承来的,则沿继承关系向上,根据需要自动调用基类的构造函数的相关部分初始化该成员
有种情况:基类存在一个private成员,该成员不能被派生类继承,但派生类的构造函数是继承基类,其中存在语句要对private成员进行初始化,这意味着在派生类的构造函数中要初始化在派生类中不存在的成员
多态性
多态
多态性是面向对象程序设计的一个强大的机制:为名称相同的方法提供不同的实现方式,继自同一基类的不同派生类可以为同名方法定义不同的功能,同一方法作用与不同类的对象,可以有不同的解释,产生不同的执行结果
虚方法
如果基类中定义了一个方法成员,我们希望在其派生类继承该方法的同时改变该方法的具体实现,则需要将基类中的该方法成员定义为虚方法,然后再派生类中重写同名的方法成员,从而实现多态性
1.只有虚方法才能被派生类重写
2.虚方法必须是非静态方法
基类中使用关键词virtual关键字将方法成员定义为虚方法,派生类中使用override关键词重写基类的虚方法,基类个派生类中对应方法成员的方法名、返回值类型、参数个数和类型必须相同
class Father { public virtual void Fun() {...} } class Son:Father { public override void Fun() //重写此方法 { base.Fun(); //使用“base.方法名”格式可以调用基类中的方法,前提是该方法不能是private修饰的方法 ... } } static void Main(string[] age) { Father f = new Son(); //基类指针指向派生类的对象 f.Fun(); //引用派生类的对象的方法 }
多态和重载
重载是在同一个类的内部中定义多个同名的方法。
多态则是在派生类中定义一个和基类一样的名字的非虚方法,会让基类中的同名虚方法被隐藏。基类中定义的虚方法在派生类中只能被重写一次!
抽象类与抽象方法
抽象类
抽象类只能作为基类,用于创建派生类,本身不能实例化,也就是不能创建对象,抽象类用abstract修饰
抽象类中的成员:(1)抽象成员 (2)非抽象成员
从抽象类派生出新的类:(1)抽象类 (2)非抽象类(必须实现基类中所有抽象成员!)
抽象方法
抽象方法只能存在于抽象类中,非抽象类不能有抽象方法
abstract class Father //定义一个抽象类,使用关键字abstract { public abstracr void Test(int x); //定义一个抽象方法,只存在抽象类中。抽象方法定义不包含实现部分,没有函数体的花括号! } class Son:Father //非抽象类继承抽象类,必须实现基类中所有的抽象成员! { public override void Test(int x) //重写抽象类的抽象方法,使用关键字override实现 { ... } }
如果希望基类的某个方法包含在所有派生类中,可以定义基类为抽象类,将该方法定义为抽象方法,则基类的所有派生类的定义中都必须重写实现该方法
密封类与密封方法
密封类
如果不希望一个类被其他类继承,可以将该类定义为密封类,就是不能作为基类的类
sealed class 类名 {...}
密封方法
如果允许某个类作为基类,同时希望类中的某个方法能够被派生类继承,但不能被派生类重写,可以将此方法定义为密封方法
只有被重写的方法才能定义为密封方法
class Father { public virtual void Test() //虚拟方法 {...} } class Son:Father { public sealed override void Test() //重写了Test()方法,为了防止此类再次被派生出的类重写Test()方法,加上了sealed密封该方法, { 重写 } //所以此类派生出的类只能继承来使用,不能重写 }
接口
public interface A //定义一个接口A { string Name{get;set;} } public interface B //定义一个接口B { void Run(); //只包含接口成员的声明,不包含实现,接口的实现必须在接口被继承后实现 } class Human:A,B //一个类可以继承多个接口 { public string name; public string Name //实现A接口的属性成员Name { get{...} set{...} } public void Run() //实现B接口的方法成员Run {...} public void Myname() //类Human自己定义的方法 {...} } calss Fish:A //一个接口可以被多个类继承 { public void Run() {...} }
接口和抽象类非常类似,但两者有以下区别:
(1)接口中不能包含方法的具体实现;抽象类中声明的方法(注意不是抽象方法!!!)可以在抽象类中具体实现
(2)接口支持多重继承,即一个类可以同时继承多个接口,也可以同时继承基类和接口,此时要把基类名写在前面,接口名写在后面;抽象类只能实现单一继承,即抽象类的派生类只有一个基类
(3)接口定义中不能为接口成员指定访问修饰符,默认为puplic;而抽象类定义中可以为接口成员指定修饰符