1、虚方法的概念:
类中的方法声明前加上了virtual 修饰符,我们称之为虚方法;
如: class A
{
public virtual void F(){} //虚方法
}
virtual修饰符表明:该基类(本例中指A类)的派生类(本例中指B类)可以
重写该方法(本例中指方法F())。
如: class B:A
{
public override void F(){} //派生类B重写类A的虚
方法F()
}
与之相对的,没有用virtual 修饰符,我们称之为非虚方法。
2、重写的概念:
是子类(即派生类)的方法覆盖父类(即基类)的虚方法。
重写的要求:
1、三相同:
(1)方法名称相同
(2)参数列表相同
(3)返回值类型相同
一句话,只需重写代码体的内容!
2、重写声明不能更改虚方法的可访问性:重写方法和虚方法必须具有相同的访问级修饰符。例如:虚方法为public的,重新方法也必须是public的。
3、可以重写基方法:必须是虚拟的(virtual)、抽象的(abstract)或重写的(override)。(非虚方法或静态方法是不可以重写的)
4、不能使用下列修饰符修改重写(override)方法(即该方法中含有override关键字):new、static、virtual、abstract
如:new public override void outwork () //这样写是不可以的
{
MessageBox.Show("子类的子类(override)下班");
}
5、重写属性:重写的属性必须与继承属性有完全相同的访问修饰符、类型和属性名,并且重写属性必须是虚拟的(virtual)、抽象的(abstract)或是重写的(override)。
6、new关键字和override关键字比较:
如果使用override重写xx方法,通过父类引用一样只能看到重写后的方法; override重写的是虚方法,那么就只剩下重写以后的方法,原来的方法被覆盖了。
如果使用new隐藏xx方法,父类子类引用各自对应方法;
new隐藏基类的方法,那么基类的方法和当前类的方法同时存在只是被隐藏了。
总结:override可以覆盖基类的方法,让基类的方法以子类的内容实现,而new不用来覆盖基类的方法,而是全新定义一个子类的方法,这个方法只属于子类,与基类的方法无关,只是名字上相同而已。
举例说明:
例一:
using System;
class A
{
public void F( ){ Console.WriteLine("A.F");}
public virtual void G( ){ Console.WriteLine("A.G");}//虚方法,在其子类中可以被重写
}
class B:A
{
new public void F( ){ Console.WriteLine("B.F");}
public override void G( ){ Console.WriteLine("B.G");}
}
class Test
{
static void Main( )
{
B b=new B( );
A a=b;
a.F( ); //值为A.F
b.F( ); //值为B.F
a.G( ); //值为B.G,因为虚方法G()被重写了
b.G( ); //值为B.G
}
}
例二:
class A
{
public virtual void F() { Console.WriteLine("A.F"); }
}
class B: A
{
public override void F() { Console.WriteLine("B.F"); }
}
class C: B
{
new public virtual void F() { Console.WriteLine("C.F"); }
}
class D: C
{
public override void F() { Console.WriteLine("D.F"); }
}
class Test
{
static void Main()
{
D d = new D();
C c = d;
B b = d;
A a = d;
a.F(); //值为B.F
b.F(); //值为B.F
c.F(); //值为D.F
d.F(); //值为D.F
}
}
例三:abstract和override使用方法:注:只有当类是abstract时才可以声明abstract方法;
abstract class Animal
{
public abstract void Drink();
public abstract void GotoBed();
}
class Dog : Animal
{
public override void Drink()
{
MessageBox.Show("小狗喝水");
}
public override void GotoBed()
{
MessageBox.Show("小狗睡觉");
}
public override string ToString()//也可:public new string ToString()
{
return "小狗";
}
}
总结:
Public abstract void pay(); abstract方法没有方法实现,必须继承
Public sealed override void pay(){} sealed方法必须是重写父类的方法
Public static void pay(){} static方法通过类名访问
Public virtual void pay(){} virtual方法子类可以对其override或new
Public new void pay(){} 父类的方法pay不一定是virtual也可以为非虚方法
Public override void pay(){} 父类的方法pay一定要是virtual
例四:new、abstract、virtual、override关键字的使用代码示例:
public abstract class People //abstract说明类People是一个抽象类不能被实例的,只能被继承
{
public People()//构造函数
{
}
public void Work() //非虚方法
{
MessageBox.Show("开始工作!");
}
public virtual void GetOffWork() //虚函数,说明此方法可以被子类重写覆盖(override)
{
MessageBox.Show("下班啦!");
}
}
public class Manage:People //继承Popele类
{
public Manage()//构造函数
{
}
new public void Work()
/*因为基类已经实现了Work方法,而在子类中又实现了Work方法,所以编译会报警,在前面加上 new(隐藏基类方法),是将警报关闭,这样就不会报错。*/
{
base.Work(); //调用基类Popele的方法。显示“开始工作”
}
public override void GetOffWork() //重写覆盖people类的方法
{
MessageBox.Show("管理员下班啦");
}
}
以上应该总结几点:
1、 如果父类方法没有加virtual关键字,即不是一个虚方法,则在子类中只能隐藏基类方法
(new),而不能覆盖(override)。
2、如果父类方法加了virtual关键字,即它是一个虚方法,在子类中一样可以隐藏(new)。
3、如果子类实现了父类相同的方法(相同的方法名称及签名),而没有new,在编译时会报警,但
编译仍然能够通过!
3、调用父类方法:base.方法名()
4、abstract类是一个抽象类,不能被实例化,只能继承
3、最后讲讲重载(overload):是在同一个类中的两个或两个以上的方法,拥有相同的方法
名,函数类型也相同,但是参数却不相同,最常见的重载的例子就是类的构造函数。