扩展或修改继承的方法、属性、索引器或事件的 abstract 或 virtual 实现需要 override 修饰符。
在以下示例中,“Lei正方形”类必须提供 GetArea 的重写实现,因为 GetArea 继承自抽象 Lei封闭形状 类:
static void Main(string[] args)
{
Lei正方形 zf4 = new ( 4 );
Console . WriteLine( zf4 . ToString ( ) );
Lei圆 yuan4 = new ( 4 );
Console . WriteLine ( yuan4 . ToString ( ) );
}
public abstract class Lei封闭形状
{
public abstract double _面积 ( );
public abstract double _周长 ( );
}
public class Lei正方形 : Lei封闭形状
{
private double _边长;
public Lei正方形 ( double 边长 ) => _边长 = 边长;
public override double _面积 ( )
{
return _边长 * _边长;
}
public override double _周长 ( )
{
return _边长 * 4;
}
public override string ToString ( )
{
return $"边长为:{_边长} 的正方形周长:{_周长 ( )};面积:{_面积 ( )}";
}
}
public class Lei圆 : Lei封闭形状
{
private double _半径;
public Lei圆 ( double 半径 ) => _半径 = 半径;
public override double _周长 ( )
{
return Math . Tau * _半径;
}
public override double _面积 ( )
{
return Math . PI * _半径 * _半径;
}
public override string ToString ( )
{
return $"半径为:{_半径} 的圆周长:{_周长 ( )};面积:{_面积 ( )}";
}
上例中,“Lei正方形”和“Lei圆”均从“Lei封闭形状”中继承了“_周长”和“_面积”方法,并(必须)提供了新的实现。通过 override 声明重写的方法称为重写基方法。override 方法必须具有与重写基方法相同的签名。override 方法支持协变返回类型。具体而言,override 方法的返回类型可从相应基方法的返回类型派生。
不能重写非虚方法或 static 方法。重写基方法必须是 virtual、abstract 或 override。
override 声明不能更改 virtual 方法的可访问性。override 方法和 virtual 方法必须具有相同级别访问修饰符。
不能使用 new、static 或 virtual 修饰符修改 override 方法。
重写属性声明必须指定与继承的属性完全相同的访问修饰符、类型和名称。只读重写属性支持协变返回类型。重写属性必须为 virtual、abstract 或 override。
人和家人
下面示例描述了基类“Lei人”和派生类“Lei家人”。
/// <summary>
/// 人的基类以及 new 过程,只描述了姓名、性别、生日和一个未实现的“昵称”
/// </summary>
/// <param name="姓名">此人姓名</param>
/// <param name="性别">此人性别</param>
public abstract class Lei人 ( string 姓名 , bool 性别 )
{
/// <summary>
/// 允许某些人不知道姓名
/// </summary>
public string? 姓名
{
get; set;
} = 姓名;
/// <summary>
/// 根据性别的 bool 返回“男”或“女”
/// </summary>
public bool _XingBie = 性别;
public string 性别
{
get
{
if ( _XingBie )
return "男";
return "女";
}
}
private DateTime _ShRi;
public DateTime 生日
{
get { return _ShRi; }
set { _ShRi = value; }
}
/// <summary>
/// 根据生日与当前时间的差距返回活了多少天
/// </summary>
public int 日龄
{
get => (DateTime . Now - _ShRi) . Days;
}
/// <summary>
/// 必须重写的“昵称”属性
/// </summary>
public abstract string 昵称
{
get; set;
}
/// <summary>
/// 重写的 ToString 方法
/// </summary>
/// <returns>“人”的字符串表示形式(姓名和性别)</returns>
public override string ToString ( )
{
return $"{姓名},{性别}";
}
}
/// <summary>
/// 可以具体化的“家人”类,继承自“人”类
/// </summary>
public class Lei家人 : Lei人
{
private string? _NiCh;
/// <summary>
/// 重写的“人”类的“昵称”属性
/// </summary>
public override string 昵称
{
get
{
if ( _NiCh is null | _NiCh . Trim ( ) == string . Empty )
return "无";
return _NiCh;
}
set => _NiCh = value;
}
/// <summary>
/// 具有“昵称”的“家人”new 过程
/// </summary>
/// <param name="姓名">家人的姓名</param>
/// <param name="性别">家人的性别</param>
/// <param name="生日">家人的生日</param>
/// <param name="昵称">家人的昵称</param>
public Lei家人 ( string 姓名 , bool 性别 , DateTime 生日 , string 昵称 ) : base ( 姓名 , 性别 )
{
this . 生日 = 生日;
this . 昵称 = 昵称;
}
/// <summary>
/// 没有“昵称”属性的“家人”new 过程
/// </summary>
/// <param name="姓名">家人的姓名</param>
/// <param name="性别">家人的性别</param>
/// <param name="生日">家人的生日</param>
public Lei家人 ( string 姓名 , bool 性别 , DateTime 生日 ) : base ( 姓名 , 性别 )
{
this . 生日 = 生日;
this . 昵称 = "";
}
/// <summary>
/// 重写的 ToString,返回“家人”的字符串表示形式
/// </summary>
/// <returns>家人的详细内容(姓名、性别、昵称(可无)、日龄)</returns>
public override string ToString ( )
{
return $"{base . ToString ( )};昵称:{this . 昵称},日龄:{this . 日龄}";
}
}
static void Main(string[] args)
{
Lei家人 LP = new ( "白芙蓉" , false , new DateTime ( 2003 , 4 , 5 ) , "死老婆" );
Lei家人 NvEr = new ( "蓝玫瑰" , false , new DateTime ( 2023 , 11 , 19 ) );
Lei家人 ErZi = new ( "白牡丹" , true , new DateTime ( 2020 , 12 , 31 ) );
Console . WriteLine ( LP . ToString ( ) );
Console . WriteLine ( ErZi . ToString ( ) );
Console . WriteLine ( NvEr . ToString ( ) );
}
上例中“Lei家人”的 ToString 是可以不重写的,这样“Lei家人”的对象的 ToString 方法直接使用“Lei人”的。“Lei家人”必须实现继承自“Lei人”的“昵称”属性,因为该属性被明确为“抽象的”(abstract)。
由于“Lei家人”的 new 过程继承自“Lei人”的 new 过程,所以关于“姓名”和“性别”的赋值直接使用“Lei人”的 new 过程。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。