继承中的virtual,override,new,abstract
写这个,只是想作个总结,刚刚看完继承章节中的这部分,乱乱的,理一下思路.
一般的继承就不再说了,现在主要说一下virtual,override,new,abstract的区别
和作用等.
先说new.平时我们都是用他来声明一个对象,当然在struct和enum中也可以使
用他,我试过,虽然不是类,也不像对象,但是可以这样使用.这里的new是在子类中
要覆盖掉父类时使用new标识符.
比如父类中有个方法:
public void GetFullName()
{}
当子类继承父类后,想改变此方法,覆盖掉父类的方法就可以使用new
public new void GetFullName()
{}
这么简单,费了这么多话.让大家失望了
使用virtual和override的目的是能够让您能调用实际被赋值给的对象
所属类中的方法,而不是基类(父类)的方法这么说说的不清楚,看代码
using System;
class Person
{
protected string firstName;
protected string lastName;
public Person()
{
}
public Person(string fn,string ln)
{
firstName=fn;
lastName=ln;
}
public virtual void GetFullName()
{
Console.WriteLine("{0} {1}",firstName,lastName);
}
}
class Employee:Person
{
public ushort hireYear;
public Employee():base()
{
}
public Employee(string fn,string ln,ushort hy):base(fn,ln)
{
hireYear=hy;
}
public override void GetFullName()
//public new void GetFullName()
{
Console.WriteLine("Employee:{0} {1}",firstName,lastName);
}
}
//A new class derived from Person...
class Contractor:Person
{
public string company;
public Contractor():base()
{
}
public Contractor(string fn,string ln,string c):base(fn,ln)
{
company=c;
}
public override void GetFullName()
//public new void GetFullName()
{
Console.WriteLine("Contractor:{0} {1}",firstName,lastName);
}
}
class NameApp
{
public static void Main()
{
Person Brad=new Person("Bradley","Jones");
Person me=new Employee("Bradley","Jones",1983);
Person Greg=new Contractor("Hill","Batfield","Data Diggers");
Brad.GetFullName();
me.GetFullName();
Greg.GetFullName();
}
}
当使用override时,显示的
Bradley Jones
Employee:Bradley Jones
Contractor:Hill Batfield
而使用new则不是,可以试试
因为父类对象调用的子类中的方法,请注意看Main中的声明对象代码
还有new单纯就是覆盖,仅仅就是覆盖调父类中的方法,而使用当前的方法
有没有virtual都是一样的,而且他也不允许父类对象调用子类中的方法.
使用override是允许父类声明的对象(当被赋值为子类时如:Father a=new Son())
可以使用子类声明的方法.
虽然基类的方法被声明为虚拟的(以便实现多态),但要根据赋值变量的数据类型来
调用相应的方法,还必须在派生类的方法中使用关键字override.可以强制派生类覆盖
基类的方法:将基类的方法声明为抽象(abstract)的.抽象方法没有方法体,由派生类提供.
using System;
class Person
{
protected string firstName;
protected string lastName;
public Person()
{
}
public Person(string fn,string ln)
{
firstName=fn;
lastName=ln;
}
public abstract void GetFullName()
}
class Employee:Person
{
public ushort hireYear;
public Employee():base()
{
}
public Employee(string fn,string ln,ushort hy):base(fn,ln)
{
hireYear=hy;
}
public override void GetFullName()
//public new void GetFullName()
{
Console.WriteLine("Employee:{0} {1}",firstName,lastName);
}
}
//A new class derived from Person...
class Contractor:Person
{
public string company;
public Contractor():base()
{
}
public Contractor(string fn,string ln,string c):base(fn,ln)
{
company=c;
}
public override void GetFullName()
//public override void GetFullName()
{
Console.WriteLine("Contractor:{0} {1}",firstName,lastName);
}
}
class NameApp
{
public static void Main()
{
//Person Brad=new Person("Bradley","Jones");
Person me=new Employee("Bradley","Jones",1983);
Person Greg=new Contractor("Hill","Batfield","Data Diggers");
//Brad.GetFullName();
me.GetFullName();
Greg.GetFullName();
}
}
对应于abstract声明的方法,我们使用的相应的标识符仍为override,如果使用new会报错.
这里给父类对象赋值为子类,但调用GetFullName方法的却是子类中的方法,因为父类中没有方法体.
总结一下,new可以使用在有virtual或无virtual的时候,但不能用在abstract中.
override对应的是virtual和abastact.和new的主要区别在于,当出现
Father a=new Sun();
如上声明对象的情况时,使用new声明的方法使用的仍是父类方法,而override声明的方法使用的是子类中的方法.
override 说明的是虚方法,new则不是。
new 为了让人清楚知道覆盖了父类方法.
override 才有实际作用,后期联编
------------------------------------------------------------------------------------------------------------------------------------------------
abstract & virtual & override & new
abstract
abstract 修饰符可以和类、方法、属性、索引器及事件一起使用。
在类声明中使用 abstract 修饰符以指示类只能是其他类的基类。
抽象类具有以下特性:
·抽象类不能实例化。
·抽象类可以包含抽象方法和抽象访问器。
·不能用 sealed 修饰符修改抽象类,这意味着该类不能被继承。
·从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实实现。
·在方法或属性声明中使用 abstract 修饰符以指示此方法或属性不包含实现。
抽象方法具有以下特性:
·抽象方法是隐式的 virtual 方法。
·只允许在抽象类中使用抽象方法声明。
·因为抽象方法声明不提供实实现,所以没有方法体;方法声明只是以一个分号结束,并且在签名后没有大括号 ({ })。例如: public abstract void MyMethod();
·实现由 overriding 方法提供,它是非抽象类的成员。
·在抽象方法声明中使用 static 或 virtual 修饰符是错误的。
除了在声明和调用语法上不同外,抽象属性的行为与抽象方法一样。
·在静态属性上使用 abstract 修饰符是错误的。
·在派生类中,通过包括使用 override 修饰符的属性声明可以重写抽象的继承属性。
virtual
virtual 关键字用于修改方法或属性的声明,在这种情况下,方法或属性被称作虚拟成员。虚拟成员的实现可由派生类中的重写成员更改。
调用虚方法时,将为重写成员检查该对象的运行时类型。将调用大部分派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员。
默认情况下,方法是非虚拟的。不能重写非虚方法。
不能将 virtual 修饰符与以下修饰符一起使用:
static abstract override
除了声明和调用语法不同外,虚拟属性的行为与抽象方法一样。
·在静态属性上使用 virtual 修饰符是错误的。
·通过包括使用 override 修饰符的属性声明,可在派生类中重写虚拟继承属性。
override(覆盖上面两种关键字修饰方法)
使用 override 修饰符来修改方法、属性、索引器或事件。重写方法提供从基类继承的成员的新实现。由重写声明重写的方法称为重写基方法。重写基方法必须与重写方法具有相同的签名。
不能重写非虚方法或静态方法。重写基方法必须是虚拟的、抽象的或重写的。
重写声明不能更改虚方法的可访问性。重写方法和虚方法必须具有相同的访问级修饰符。
不能使用下列修饰符修改重写方法:
new static virtual abstract
重写属性声明必须指定与继承属性完全相同的访问修饰符、类型和名称,并且重写属性必须是虚拟的、抽象的或重写的。





























































































new
使用 new 修饰符显式隐藏从基类继承的成员。若要隐藏继承的成员,请使用相同名称在派生类中声明该成员,并用 new 修饰符修饰它。
类成员声明中可以使用与一个被继承的成员相同的名称或签名来声明一个成员。发生这种情况时,就称该派生类成员隐藏了基类成员。隐藏一个继承的成员不算是错误,但这确实会导致编译器发出警告。若要取消此警告,派生类成员的声明中可以包含一个 new 修饰符,表示派生成员是有意隐藏基成员的。







































































-----------------------------------------------------------------------------------------------------------------------------------
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的方法。显示“开始工作”
//MessageBox.Show("管理员开始工作罗!");
}
public override void GetOffWork() //覆盖基类的方法
{
MessageBox.Show("管理员下班啦");
}
}
public class Employee():People
{
public Employee()
{}
new public void GetOffWork() //virtual方法仍然可以 new
{
MessageBox.Show("职员下班啦!");
}
}
以上应该应该几点:
1、如果父类方法没有加virtual关键字,即不是一个虚方法,则在子类中只能隐藏基类方法,而不能覆盖。
2、如果父类方法加了virtual关键字,即它是一个虚方法,在子类中一样可以隐藏。
3、如果子类实现了父类相同的方法(相同的方法名称及签名),而没有new,在编译时会报警,但编译仍然能够通过!
3、调用父类方法:base.方法名()
4、abstract类是一个抽象类,不能被实例化