【转载】C# 密封类及相关关键字

159 阅读6分钟

原文链接

版权声明:本文为CSDN博主「AI浩」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:blog.csdn.net/hhhhhhhhhhw…

正文

密封类

通过在类定义前面放置关键字 sealed,可以将类声明为密封类。例如:

public sealed class D
{

    // Class members here.
}

密封类不能用作基类。因此,它也不能是抽象类。密封类禁止派生

由于密封类从不用作基类,所以有些运行时优化可以使对密封类成员的 调用略快

重写基类虚成员的派生类成员,如方法、字段、属性或事件,可被声明为密封成员。

在后续的派生类中,这将取消该成员的虚效果。方法是在类成员声明中将 sealed 关键字置于 override 关键字的前面。例如:

public class D : C
{
    public sealed override void DoWork() { }

}

一、特点

  1. 使用 sealed 关键字来定义密封类。
  2. 密封类 不能 被继承。
  3. 在密封类 不能 定义虚函数,不能 定义抽象函数。
  4. 可以使用 sealed 关键字来密封方法,但是 只有 在覆盖基类的方法时才能使用 sealed 关键字。
  5. 使用 sealed 关键字密封的方法 不能 被覆盖,防止派生类进一步重写该方法,但能被重载,能被隐藏。
  6. 在使用 sealed 关键字时,不能 同时使用 abstractvirtual 关键字。

注意事项:

  • 密封类不能作为基类被继承,但它可以继承别的类或接口。
  • 在密封类中不能声明 受保护 成员或 方法,因为受保护成员和只能从派生类进行访问,而虚成员只能在派生类中重写。
  • 由于密封类的不可继承性,因此密封类不能声明 抽象 的。

二、示例

using System;
using System.Collections.Generic;
using System.Text;

namespace TestSealedClass_01
{   
    // 密封类 不能被继承
    sealed class A
    {
        public void Method1()
        {}

        //错误,在密封类中不能定义虚函数
        //public virtual void Method2()
        //{}

        //错误,在密封类中不能定义抽象函数
        //public abstract void Method3();
    }

    //class B : A   //错误,密封类 A 不能被继承
    //{}

    class AutoMobile
    {
        public virtual void Display()
        {
            Console.WriteLine("这是基类 AutoMobile");
        }

        //Display() 方法不是重写,所以不能使用 sealed 关键字
        //public sealed void Display()
        //{
        //    Console.WriteLine("这是基类 AutoMobile");
        //}
    }

    class Car : AutoMobile
    {
        //使用 sealed 关键字来密封方法
        public sealed override void Display()
        {
            Console.WriteLine("这是派生类 Car");
        }

       public void Display(string mark) //使用 sealed 关键字密封的方法,能被重载
       {
            Console.WriteLine("这是派生类 Car:{0}", mark);
       }
    }

    class SmallCar : Car
    {
        //使用 sealde 关键字密封的方法,不能被覆盖
        //public override void Display()
        //{}
        
        //使用 sealde 关键字密封的方法,能被隐藏
        
        public new void Display()
        {  Console.WriteLine("这是派生类 Car"); }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Car car = new Car();
            car.Display();
        }
    }
}

C# 中 abstract 和 virtual 的区别

C# 中 abstractvirtual 比较容易混淆,都与继承有关,并且涉及 override 的使用。下面讨论一下二者的区别:

一、virtual 方法(虚方法)

virtual 关键字用于在基类中修饰方法。

virtual 的使用会有两种情况:

  • 情况1:在基类中定义了 virtual 方法,但在派生类中没有重写该虚方法。那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法。
  • 情况2:在基类中定义了 virtual 方法,然后在派生类中使用 override 重写该方法。那么在对派生类实例的调用中,该虚方法使用的是派生重写的方法。

二、abstract 方法(抽象方法)

abstract 关键字只能用在 抽象类 中修饰方法,并且没有具体的实现。抽象方法的实现 必须 在派生类中使用 override 关键字来实现。

接口和抽象类最本质的区别

  • 抽象类是一个不完全的类,是对对象的抽象,
  • 而接口是一种行为规范。

三、相关关键字

static

当一个方法被声明为 static 时,这个方法是一个静态方法,编译器会在编译时保留这个方法的实现。也就是说,这个方法属于类,但是不属于任何成员,不管这个类的实例是否存在,它们都会存在。就像入口函数 static void main,因为它是静态函数,所以可以直接被调用。

virtual

当一个方法被声明为 virtual 时,它是一个虚拟方法,直到你使用 ClassName variable = new ClassName(); 声明一个类的实例之前,它都不存在于真实的内存空间中。这个关键字在类的继承中非常常用,用来提供类方法的多态性支持。

abstract

抽象方法声明使用,是 必须 被派生类覆写的方法,抽象类就是用来被继承的;可以看成是没有实现体的虚方法;如果类中包含抽象方法,那么类就 必须 定义为抽象类,不论是否还包含其他一般方法;抽象类不能有实体的。

override

是在子类中重写父类中的方法,两个函数的函数特征(函数名、参数类型与个数)相同。用于扩展或修改继承的方法、属性、索引器或事件的抽象或虚拟实现。提供从基类继承的成员的新实现,而通过 override 声明重写的方法称为基方法。

注意事项:

  1. 重写基方法必须具有与 override 方法相同的签名。
  2. override 声明不能更改 virtual 方法的可访问性,且 override 方法与 virtual 方法必须具有相同级别访问修饰符。
  3. 不能用 newstaticvirtual 修饰符修改 override 方法。
  4. 重写属性声明必须指定与继承的属性完全相同的访问修饰符、类型和名称。
  5. 重写的属性必须是 virtualabstractoverride
  6. 不能重写非虚方法或静态方法。
  7. 父类中有 abstract,那么子类同名方法必定有 override,若父类中有 virtual 方法,子类同名方法不一定是 override,可能是 overload
  8. override 必定有父子类关系。

overload

同一个类方法名 相同参数返回值 不同 的多个方法即为方法重载。

注意事项

  1. 出现在同一个类中。
  2. 参数列表不同或返回类型和参数列表都不同,只有返回类型不同不能重载。(参数列表包括参数个数和参数类型)

overwrite

new 实现。在子类中用 new 关键字修饰定义的与父类中 同名 的方法,也称为覆盖,覆盖不会改变父类方法的功能。