Files
2026-06-21 09:51:55 +08:00

5.4 KiB

密封函数

概念: 密封函数指的是使用 sealed 修饰的==重写成员== 在 C# 里常见写法是 sealed override

准确一点说: C# 里通常叫“密封方法”或“密封重写成员” 有些教程会说“密封函数”,初学阶段可以理解成:==不允许下一级子类继续重写的方法==

通常用法:

  1. 父类允许子类重写某个方法
  2. 某个子类重写后,认为这个实现已经定死
  3. 允许这个子类继续被继承
  4. 但不允许更下一级子类再改这个方法

语法

class 子类名 : 父类名
{
	public sealed override void 方法名()
	{

	}
}

注意: sealed 修饰方法时,必须和 override 一起使用


基础案例

class Animal
{
	public virtual void Speak()
	{
		Console.WriteLine("动物叫");
	}
}

class Dog : Animal
{
	public sealed override void Speak()
	{
		Console.WriteLine("狗叫");
	}
}

class Husky : Dog
{
	// 这里不能再 override Speak()
}

理解:

  1. Animal.Speak() 是虚方法,允许被重写
  2. Dog.Speak() 重写了父类方法
  3. Dog.Speak() 又被 sealed 密封
  4. Husky 可以继承 Dog
  5. Husky 不能继续重写 Speak()

sealed class 和 sealed override 的区别

密封类:

sealed class Dog : Animal
{

}

含义: 整个 Dog 类不能再被继承

密封函数:

class Dog : Animal
{
	public sealed override void Speak()
	{
		Console.WriteLine("狗叫");
	}
}

含义: Dog 类仍然可以被继承 但是 Speak() 不能再被下一级子类重写

对比:

  1. sealed class:封住整个类
  2. sealed override:只封住某个已经重写的成员

这个点可以和密封类一起记。


为什么密封函数必须是 override

错误写法:

class Dog
{
	public sealed void Speak()
	{
	}
}

原因: 普通方法本来就不能被 override 没有必要再用 sealed 封住

正确理解: sealed 修饰方法时,是在说: “这个方法原本处在可重写链条上,但从我这里开始不准继续重写”

所以它必须修饰已经重写的成员,也就是 sealed override


多级继承案例

class A
{
	public virtual void Test()
	{
		Console.WriteLine("A");
	}
}

class B : A
{
	public override void Test()
	{
		Console.WriteLine("B");
	}
}

class C : B
{
	public sealed override void Test()
	{
		Console.WriteLine("C");
	}
}

class D : C
{
	// public override void Test()
	// {
	//     Console.WriteLine("D");
	// }
}

调用:

A a = new C();
a.Test(); // C

理解:

  1. A.Test() 开启虚方法
  2. B.Test() 继续重写
  3. C.Test() 重写并密封
  4. D 仍然可以继承 C
  5. D 不能再重写 Test()

密封属性

sealed override 不只可以用于方法,也可以用于属性。

class Character
{
	public virtual int MaxHp
	{
		get { return 100; }
	}
}

class Boss : Character
{
	public sealed override int MaxHp
	{
		get { return 1000; }
	}
}

后续子类不能再重写 MaxHp


和多态的关系

密封函数不会取消已有多态效果。

Animal animal = new Dog();
animal.Speak(); // 狗叫

Dog.Speak() 仍然会通过多态被调用。

sealed override 只是限制: 后续子类不能继续改这个方法

也就是说:

  1. 对上层父类来说,它仍然是重写后的多态方法
  2. 对下层子类来说,它已经不能再被重写

常见错误

错误1:普通方法前写 sealed

class A
{
	public sealed void Test()
	{
	}
}

sealed 不能这样修饰普通方法。


错误2:只写 sealed 不写 override

class B : A
{
	public sealed void Test()
	{
	}
}

密封重写成员必须写成 sealed override


错误3:父类方法不是虚方法

class A
{
	public void Test()
	{
	}
}

class B : A
{
	public sealed override void Test()
	{
	}
}

父类方法不是 virtual / abstract / override,子类不能 override,也就不能 sealed override


什么时候用密封函数

适合用的情况:

  1. 某个重写逻辑非常关键,不希望后续子类改掉
  2. 父类设计允许多态,但某一层子类希望终止这个方法的重写链
  3. 框架或基础类库中需要保证关键行为稳定

初学阶段: 先知道这个语法和作用即可 自己写练习代码时用得不多


注意

  1. 密封函数常见写法是 sealed override
  2. 它只能用于已经重写的成员
  3. 它阻止下一级子类继续重写这个成员
  4. 它不会阻止当前类被继承
  5. 如果想阻止整个类被继承,用 sealed class
  6. 方法、属性、索引器、事件等重写成员都可以理解这个规则

一句话记忆

==sealed override 表示这个重写到我这里为止,后面的子类不能再改。==


面试/复习时怎么说

可以这样答:

“密封函数通常指 sealed override 修饰的重写方法。
它表示当前类重写了父类的虚方法,但不允许更下一级子类继续重写。
它和密封类不同,密封类是不允许整个类被继承,而密封函数只是禁止某个重写成员继续被重写。”


引用:

  1. Microsoft Learn: sealed (C# Reference)
  2. Microsoft Learn: override (C# Reference)

#密封函数 #密封方法 #核心