virtual 用于修饰方法、事件、属性和索引器,指示该成员可以被派生类继承或重写。
internal class Program
{
static void Main(string[] args)
{
LeiP p = new ( );
Console . WriteLine ( $"继承的方法:{p . FF ( )}" );
}
}
class LeiJi
{
public virtual int FF ( )
{
return 1 + 1;
}
}
class LeiP : LeiJi
{
}
上例中的类 LeiP 继承自 LeiJi,由于 LeiP 是空的(没有重写 FF),因此当声明 LeiP 对象 p 后,可以使用继承自 LeiJi 的方法 FF,输出:
继承的方法:2
继承的类,也可以重写基类的 virtual 成员,以提供新的实现:
internal class Program
{
static void Main(string[] args)
{
LeiP p = new ( );
Console . WriteLine ( $"重写的方法:{p . FF ( )}" );
}
}
class LeiJi
{
public virtual int FF ( )
{
return 1 + 1;
}
}
class LeiP : LeiJi
{
public override int FF ( )
{
return 1 + 2;
}
}
上例中的类 LeiP 继承自 LeiJi,由于 LeiP 重写(override)了 FF,因此当声明 LeiP 对象 p 后,并非使用继承自 LeiJi 的方法 FF,而是输出:
重写的方法:3
virtual 成员既可以被派生类中的替代成员(override)更改,也可以直接继承。
注解
当调用 virtual 方法时,将检查对象的运行时类型是否有重写成员。如果没有派生类重写成员,则调用其基类中的重写成员,该成员可能是顶级基类的原始成员。
internal class Program
{
static void Main(string[] args)
{
LeiPs ps = new ( );
Console . WriteLine ( $"重写的方法:{ps . FF ( )}" );
}
}
class LeiJi
{
public virtual int FF ( )
{
return 1 + 1;
}
}
class LeiP : LeiJi
{
public override int FF ( )
{
return 1 + 2;
}
}
class LeiPs : LeiP
{
}
上例中的 LeiPs 继承自 LeiP,并没有重写 FF,因此对象 ps 的 FF 方法是继承其基类 LeiP 的 FF,返回 3;倘若 LeiP 也没有重写 FF,则会继承 LeiJi 的 FF,返回 2。
缺省情况下,方法是非虚的。不能重写非虚方法。
下面的例子展示了一个虚拟属性:
class LeiJi
{
// 虚拟自动实现属性。重写只有在实现 get 和 set 访问器时才能提供专门的行为
public virtual required string _名字
{
get; set;
}
// 带背域的普通 virtual 属性
private int _数;
public virtual int 数
{
get
{
return _数;
}
set
{
_数 = value;
}
}
class LeiP : LeiJi
{
private string? _Name;
// 用普通属性覆盖自动实现的属性,以提供专门的访问器行为
public override required string _名字
{
get
{
if ( _Name != null )
return _Name;
else
return "未知";
}
set
{
if ( ! string.IsNullOrEmpty( value ) )
{
_Name = value;
}
else
{
_Name = "未知";
}
}
}
}
除声明和调用语法不同外,虚拟属性的行为与虚拟方法相似。
通过包括使用 override 修饰符的属性声明,可在派生类中替代虚拟继承属性。
示例
在该示例中,Lei形状 类包含 x、y 两个坐标和 面积 ( ) 虚拟方法。不同的形状类(如 Lei圆、Lei圆柱 和 Lei球)继承 Lei形状 类,并为每个图形计算表面积。每个派生类都有各自的 面积 ( ) 替代实现。
请注意,继承的类 Lei圆、Lei圆柱 和 Lei球 均使用初始化基类的构造函数。
下面的程序根据与 面积 ( ) 方法相关联的对象,通过调用 面积 ( ) 方法的适当实现,计算并显示每个图形的适当面积。
{
static void Main ( string [ ] args )
{
double bj = 1.25 , g = 6.98;
Lei形状 y = new Lei圆 ( bj );
Console . WriteLine ( $"圆的面积:{ y . 面积 ( ):F2}" );
Lei形状 yz = new Lei圆柱 ( bj , g );
Console . WriteLine ( $"圆柱的表面积:{yz . 面积 ( ):F2}" );
Lei形状 q = new Lei球 ( bj );
Console . WriteLine ( $"球的表面积:{q . 面积 ( ):F2}" );
}
}
public class Lei形状
{
protected double _x , _y ;
public Lei形状 ( )
{
}
public Lei形状 ( double x , double y )
{
_x = x;
_y = y;
}
public virtual double 面积 ( )
{
return _x * _y;
}
}
public class Lei球 ( double 半径 ) : Lei形状 ( 半径 , 0 )
{
public override double 面积 ( )
{
return 4 * Pi * Pow (_x , 2 );
}
}
public class Lei圆 ( double 半径 ) : Lei形状( 半径 , 0 )
{
public override double 面积 ( )
{
return Pi * Pow ( _x , 2 );
}
}
public class Lei圆柱 ( double 底面半径 , double 高 ) : Lei形状 ( 底面半径 , 高 )
{
public override double 面积 ( )
{
return Tau * Pow ( _x , 2 ) + Tau * _x * _y;
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。