一、抽象(abstract)
只有类(class)才可以抽象,结构体(struct)不能 ,抽象类不能实例化
class Program
{
abstract class People
{
}
static void Main(string[] args)
{
People people = new People(); //错误写法
}
}
报错提示:CS0144 无法创建抽象类或接口“Program.People”的实例
//错误案例
abstract class People
{
abstract void Get();
}
报错提示:CS0621 '“Program.People.Get()”: 虚拟成员或抽象成员不能是私有的
abstract class People
{
internal abstract void Get() { } //报错
}
报错提示:CS0500 '“Program.People.Get()”无法声明主体,因为它标记为 abstract
abstract class People
{
internal abstract void Get();
protected abstract int Age { get; set; }
public abstract int this[int index] { get; set; }
public abstract event Action ChangeEvent;
}
class Man : People
{
internal override void Get() { }
protected override int Age { get; set; }
public override int this[int index]
{
get { return Age; }
set { Age = value; }
}
public override event Action ChangeEvent;
}
总结:
- 抽象只针对于 class,struct不能抽象
- 抽象成员只能存在于抽象类中(抽象类中的成员也可以不是抽象的)
- 可以抽象的成员有(方法、属性、索引器、事件),字段不能抽象
- 抽象成员必须标记为可以被子类访问的修饰(public、internal 或protected)
- 子类重写抽象父类中的成员时访问修饰符要一致
- 标记为抽象的成员是不能有实体的
二、虚拟(virtual)
//错误案例
class People
{
virtual void Get() { }
}
报错提示:CS0621 '“Program.People.Get()”: 虚拟成员或抽象成员不能是私有的
class People
{
public virtual void Get() { }
protected virtual int Age { get; set; }
public virtual int this[int index]
{
get { return Age; }
set { Age = value; }
}
public virtual event Action ChangeEvent;
}
class Man : People
{
public override void Get() { }
protected override int Age { get; set; }
public override int this[int index]
{
get { return Age; }
set { Age = value; }
}
public override event Action ChangeEvent;
}
virtual 与 abstract 的异同点
相同点:
- 都可以修饰的成员有(方法、属性、索引器、事件),字段不行
- 成员都必须标记为可以被子类访问的修饰(public、internal 或protected)
- 子类重写父类中的成员时访问修饰符要一致
- 子类中需重写的成员都要标记为 override
不同点:
- abstract可以修饰于class,但virtual不行(只能修饰于成员)
- abstract只能存在于抽象类中,virtual抽象类和不是抽象的类都可以
- abstract修饰的成员不能有实体,但virtual必须有实体
- 在子类中,abstract成员必须重写,virtual可以不重写
三、密封(sealed)
class A { }
sealed class B : A { }
class C : B { }
报错提示:CS0509 “C”: 无法从密封类型“B”派生
class A
{
protected virtual void Get() { }
protected virtual void Set() { }
}
class B : A
{
protected sealed override void Get() { }
protected override void Set() { }
}
class C : B
{
protected override void Set() { }
protected override void Get() { }
}
报错提示: CS0239 “C.Get()”: 继承成员“B.Get()”是密封的,无法进行重写
总结:
- 应用于某个类时,
sealed
修饰符可阻止其他类继承自该类- 对替代基类中的虚方法或属性的方法或属性使用
sealed
修饰符, 防止派生类替代特定虚方法或属性- 将 abstract 修饰符与密封类结合使用是错误的,因为抽象类必须由提供抽象方法或属性的实现的类来继承
- 应用于方法或属性时,
sealed
修饰符必须始终与 override 结合使用
四、接口(interface)
//错误案例
interface IPeople
{
public void Get();
}
报错提示:CS8703 在 C# 7.3 中,修饰符 "public" 对此项无效。
interface IPeople
{
void Get();
}
class Man: IPeople
{
void Get() { } //错误
}
报错提示:CS0737 '“Program.Man”不实现接口成员“Program.IPeople.Get()”。“Program.Man.Get()”无法实现接口成员,因为它不是公共的。
interface IPeople
{
void Get();
int Age { get; set; }
int this[int index] { get; set; }
event Action ChangeEvent;
}
class Man : IPeople
{
public void Get() { }
public int Age { get; set; }
public int this[int index]
{
get { return Age; }
set { Age = value; }
}
public event Action ChangeEvent;
}
总结:
- interface命名一般以(I)开头
- 接口可以包含的成员有(方法、属性、索引器、事件),字段不行
- 接口中的成员不能有访问修饰符
- 接口中的成员不能实现实体
- 子类必须实现所有接口的成员
- 子类中接口成员都必须标记为public(不能带override)