一、定义:
virtual:用于修饰方法、属性、索引器或事件声明,并使它们可以在派生类中被重写。
abstract:表示所修饰的内容缺少实现或未完全实现。可用于类、方法、属性、索引器和事件。在类声明中使用abstract修饰符,用以指示某个类只能是其他类的基类。标记为抽象的成员,其所在的类必须声明为抽象类。抽象类无法被实例化,抽象成员必须通过从抽象类派生的类来实现。
二、使用方式:
virtual:
父类:public virtual string ToString(){return "a";}
子类:public override string ToString(){return "b";}
abstract:
父类:public abstract string ToString();
子类:public override string ToString(){return "a";}
三、特点:
virtual
1. 虚拟成员的实现可由派生类中的重写成员更改。
2. 调用虚方法时,将为重写成员检查该对象的运行时类型。将调用大部分派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员。
3. 默认情况下,方法是非虚拟的。而非虚方法不能重写。virtual修饰符不能与static、abstract,private或override修饰符一起使用。
4. 用override关键字进行重写方法。
abstract
1. 抽象类
a) 抽象类不能实例化。
b) 抽象类可以包含抽象方法和抽象访问器。
c) 不能用sealed修饰符修饰抽象类,因为这两个修饰符的含义是相反的。采用sealed修饰符的类无法继承,而abstract修饰符要求对类进行继承。
d) 从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实际实现。
2. 抽象方法
a) 抽象方法是隐式的虚方法。
b) 抽象方法必须存在于抽象类中,而子类必须重写,除非子类也是抽象的。
c) 用override关键字进行重写方法。
d) 在方法或属性声明中使用abstract修饰符以表明方法或属性不包含实现。
e) 因为抽象方法声明不提供实际的实现,所以没有方法体;方法声明只是以一个分号结束,并且在签名后没有大括号{ }。
3. 抽象方法必须存在于抽象类中
4. 在抽象方法声明中不能使用static或virtual修饰符。除了在声明和调用语法上不同外,抽象属性的行为与抽象方法一样。
四、区别:
| virtual | abstract |
名称 | 虚拟 | 抽象 |
使用方式 | 用来修饰方法、属性、索引器或事件 | 用来修饰类、方法、属性、索引器和事件 |
相同点 | 用来修饰父类 不能用private修饰 父类修饰的方法不能是private 子类对应的方法都必用override进行重写 | |
区别 | 父类必须有实现 | 父类必须没有实现 |
可以被子类重写 | 必须被子类重写 | |
不能用来修饰类 | 可用来修饰类 | |
为免程序员在子类中不小心重写父类方法,须在父类方法前加virtual,在子类方法前添加override。 若不希望重写,则子类方法须用new隐藏原方法(非必须,但会出现警告) | 如果类方法被abstract修饰,则该类前也必须添加abstract,因为只有抽象类才可以有抽象方法 | |
若子类中不重写,调用子类该方法时,调用父类该方法。 若子类中重写,调用子类该方法时,调用子类该方法。 | 子类中必须重写,否则会出现报错 | |
声明一个类的实例之前,它都不存在于真实的内存空间中 | 不能被实例化 |
五、实例:
//virtual:
class A
{
public virtual string ToString(){return "a";}
public virtual string ToString1(){return "a";}
//virtual类型必须有实现
}
class B : A
{
public override string ToString(){return "b";}
//public virtual string ToString1(){return "b";}
//virtual类型可以不重写
}
//abstract:
abstract class A
//有abstract类型成员或方法时,类也必须为abstract
{
public abstract string ToString();
public abstract string ToString1();
//abstract类型必须没有实现
}
class B : A
{
public override string ToString(){return "b";}
public override string ToString1(){return "b";}
//abstract类型必须重写}