虚方法和覆写方法
虚方法可以使基类的引用访问"升至"派生类中
可以使用基类引用调用派生类的方法,只需满足下面的条件
- 派生类的方法和基类的方法有相同的签名和返回类型
- 基类的方法使用virtual标注
- 派生类的方法使用override标注
class Program
{
static void Main(string[] args)
{
MyDerivedClass derived = new MyDerivedClass();
MyBaseClass mybc = (MyBaseClass)derived;
derived.Print();
mybc.Print();
Console.ReadLine();
}
} class MyBaseClass //基类
{
virtual public void Print()
{
Console.WriteLine("基类");
}
} class MyDerivedClass : MyBaseClass //派生类
{
public override void Print()
{
Console.WriteLine("派生类");
}
}
上面代码阐明了virtual和override方法。
关于virtual和override的信息如下
- 覆写和被覆写的方法必须有相同的可访问性
- 不能覆写static方法或非虚方法
- 方法,属性和索引器,事件都可以被声明为virtual和override
覆写标记为override的方法
- 当使用对象的基类部分的引用调用一个覆写方法时。方法的调用被沿派生层上溯执行,一直到标记为override的方法的最高派生版本
- 如果在更高的派生级别有该方法的其他声明,但没有被标记为override,那么它们不会别调用
class MyBaseClass //基类
{
virtual public void Print()
{
Console.WriteLine("基类");
}
} class MyDerivedClass : MyBaseClass //派生类
{
public override void Print()
{
Console.WriteLine("派生类");
}
}
class SecondDerived : MyDerivedClass//最高派生类
{
//to
}
情况1:使用override声明print
如果把SecondDerived的Print方法声明为override,那么他会覆写方法的全部两个派生级别的版本
class SecondDerived : MyDerivedClass//最高派生类
{
public override void Print()
{
Console.WriteLine("第二派生类");
}
} static void Main(string[] args)
{
SecondDerived derived = new SecondDerived();
MyBaseClass mybc = (MyBaseClass)derived;
derived.Print();
mybc.Print();
Console.ReadLine();
}
情况2:使用new声明Print
class SecondDerived : MyDerivedClass//最高派生类
{
new public void Print()
{
Console.WriteLine("第二派生类");
}
} static void Main(string[] args)
{
SecondDerived derived = new SecondDerived();
MyBaseClass mybc = (MyBaseClass)derived;
derived.Print();
mybc.Print();
Console.ReadLine();
}
覆盖其他成员类型
class MyBaseClass //基类
{
//virtual public void Print()
//{
// Console.WriteLine("基类");
//} private int _myInt = ;
virtual public int Myproerty
{
get { return _myInt; }
}
} class MyDerivedClass : MyBaseClass //派生类
{
//public override void Print()
//{
// Console.WriteLine("派生类");
//}
private int _myInt = ;
public override int Myproerty
{
get
{
return _myInt;
}
}
} static void Main(string[] args)
{
MyDerivedClass derived = new MyDerivedClass();
MyBaseClass mybc = (MyBaseClass)derived;
Console.WriteLine(derived.Myproerty);
Console.WriteLine(mybc.Myproerty);
Console.ReadLine();
}
构造函数的执行
要创建对象的基类部分,需要隐试调用基类的某个构造函数作为创建实例过程的一部分
继承层次链中的每个类在执行自己的构造函数体之前执行他的基类构造函数
class MyBaseClass //基类
{
public MyBaseClass()//2 基类构造函数调用
{ }
} class MyDerivedClass : MyBaseClass //派生类
{ int _myInt = ; //1 成员初始化
public MyDerivedClass() //3 构造函数体执行
{ } }
构造函数初始化语句
有两种形式的构造函数初始化语句
- 第一种形式使用关键字base并指明使用哪一个基类构造函数
- 第二种形式使用关键字this并指明应该使用当前类的哪一个构造函数
抽象成员
抽象成员是指被设计为被覆写的函数成员
抽象成员的特征
- 必须是一个函数成员,也就是说,字段和常量不能为抽象成员
- 必须用abstract修饰符标记
- 不能有实现代码块。抽象成员的代码用分号表示
抽象成员只可以在抽象类中声明,一共有4种类型的成员可以声明为抽象的
- 方法
- 属性
- 事件
- 索引
抽象成员的其他注意事项
- 尽管抽象成员必须在派生类中用相应的,但不能把virtual修饰符附加到abstract修饰符
- 类似虚成员,派生类中抽象成员的实现必须指定override修饰符
抽象类
抽象类是指设计为被继承的类,抽象类只能被用作其他类的基类
- 不能创建抽象类的实例
- 抽象类使用abstract修饰符声明
- 抽象类可以包含抽象成员或普通的非抽象成员。
- 抽象类可以自己派生自另一个抽象类
- 任何派生自抽象类的类必须使用override关键字实现该类所有的抽象成员,除非派生类自己也是抽象类
abstract class AbClass //抽象类
{
public void A() //普通方法
{
Console.WriteLine("我是抽象类");
}
abstract public void B(); //抽象方法 } class MyDerivedClass : AbClass //派生类
{
public override void B()
{
Console.WriteLine("我是派生类");
} } static void Main(string[] args)
{
MyDerivedClass derived = new MyDerivedClass();
derived.A();
derived.B();
Console.ReadLine();
}
密封类
密封类只能被用作独立的类,它不能被用作基类
密封类使用sealed修饰符标注
静态类
静态类中所有的成员都是静态的。静态类用于存放不受实例数据影响的数据和函数。
- 静态类必须标记为static
- 类的所有成员必须是静态的
- 类可以有一个静态构造函数,但不能有实例构造函数,不能创建类的实例
- 静态类是隐试密封的,也就是说,不能继承静态类
扩展方法
扩展方法的重要要求如下
- 声明扩展方法的类必须声明为static
- 扩展方法本身必须为static
- 扩展方法必须包含关键字this作为他的第一个参数类型,并在后面跟着它所扩展的类的名称