簡體   English   中英

C#中的密封方法

[英]Sealed method in C#

我是 C# 新手。我正在閱讀有關 Sealed 關鍵字的信息。我了解了 Sealed 類。我已經閱讀了有關 Sealed 方法的一行,我們也可以在其中創建 Sealed 方法。該行是(通過將方法聲明為已密封,我們可以避免進一步覆蓋此方法。 )我創建了一個演示,但不明白上述行和密封方法的含義。 以下是我的代碼:-

using System;

namespace ConsoleApplication2
{
    class Program:MyClass
    {
        public override sealed void Test()
        {
            Console.WriteLine("My class Program");
        }
        static void Main(string[] args)
        {
            Program obj = new Program();
            obj.Test();
            Console.ReadLine();
        }
    }

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


}

請告訴我為什么我們使用 Sealed 方法以及 Sealed 方法的優點是什么。

好吧,您僅使用兩個繼承級別進行測試,並且您還沒有達到“進一步覆蓋”方法的地步。 如果你把它變成三個,你可以看到sealed作用:

class Base {
   public virtual void Test() { ... }
}
class Subclass1 : Base {
   public sealed override void Test() { ... }
}
class Subclass2 : Subclass1 {
   public override void Test() { ... } // Does not compile!
   // If `Subclass1.Test` was not sealed, it would've compiled correctly.
}

密封是不能成為另一個派生類的基類的類。

在未密封類的密封方法是不能在派生類這個類的被覆蓋的方法。

為什么我們使用密封方法? 密封方法有哪些優點?

那么,為什么要使用虛方法呢? 提供一個可以自定義類行為的點 那么為什么要使用密封方法呢? 提供一個點,保證您不會在任何派生類的行為中發生關於此方法的進一步更改

可以自定義類的行為的點很有用但很危險 它們很有用,因為它們使派生類能夠改變基類的行為。 它們很危險……等等……因為它們使派生類能夠改變基類的行為 虛擬方法基本上允許第三方讓你的類做你從未預料到或測試過的瘋狂事情。

我喜歡編寫能夠滿足我的預期和測試的代碼。 密封方法允許您繼續允許類的某些部分被覆蓋,同時使密封方法具有無法進一步定制的有保證的、可測試的、穩定的行為。

好吧,如果您不希望任何派生類進一步覆蓋您的方法,則只能在方法上使用“密封”。 如果方法未聲明為虛擬方法且未覆蓋另一個虛擬方法,則默認情況下它們是密封的。 (在 Java 中,默認情況下方法是虛擬的 - 要實現“默認”C# 行為,您必須將方法標記為final 。)

我個人喜歡小心地控制繼承——我更喜歡盡可能密封整個類。 但是,在某些情況下,您仍然希望允許繼承,但要確保不會進一步覆蓋某些方法。 一種用途可能是有效地模板化方法,例如用於診斷:

public sealed override void Foo(int x)
{
    Log("Foo called with argument: {0}", x);
    FooImpl(x);
    Log("Foo completed");
}

protected abstract void FooImpl(int x);

現在子類不能直接覆蓋Foo - 他們必須覆蓋FooImpl ,所以我們的行為將始終在其他代碼調用Foo時執行。

模板當然可能是出於其他原因 - 例如強制執行參數驗證的某些方面。

根據我的經驗,密封方法並不經常使用,但我很高興有這種能力。 (我只是希望類在默認情況下是密封的,但這是另一個對話。)

密封方法

密封方法用於定義虛擬方法的覆蓋級別。

Sealed 關鍵字始終與 override 關鍵字一起使用。

密封方法的實際演示

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

namespace sealed_method
{
    class Program
    {
        public class BaseClass
        {

            public virtual void Display()
            {
                Console.WriteLine("Virtual method");
            }
        }

       public class DerivedClass : BaseClass
        {
            // Now the display method have been sealed and can;t be overridden
            public override sealed void Display()
            {
                Console.WriteLine("Sealed method");
            }
        }

       //public class ThirdClass : DerivedClass
       //{

       //    public override void Display()
       //    {
       //        Console.WriteLine("Here we try again to override display method which is not possible and will give error");
       //    }
       //}

        static void Main(string[] args)
        {

            DerivedClass ob1 = new DerivedClass();
            ob1.Display();

            Console.ReadLine();
        }
    }
}

現在,如果您聲明 Program 的子類,您將無法覆蓋 Test 方法,這就是重點。

在大多數情況下,您不需要密封方法,但是當您為某些插件系統開發基類時,它們可以證明自己很有用,第三方開發人員必須擴展這些基類才能創建自己的插件。 您可以保留一些服務數據,例如插件名稱和是否啟用,並使用密封的方法和屬性來完成,這樣插件開發人員就不會亂七八糟。 這是密封成員派上用場的一種情況

首先,讓我們從定義開始; Sealed 是一個修飾符,如果應用於類,則使其不可繼承,如果應用於虛擬方法或屬性,則使其不可超越

public sealed class A { ... }
public class B 
{
    ...
    public sealed string Property { get; set; }
    public sealed void Method() { ... }
}

其用法的一個示例是特殊的類/方法或屬性,其中潛在的更改可以使它們按預期停止工作(例如,System.Drawing 命名空間的 Pens 類)。

...
namespace System.Drawing
{
    //
    // Summary:
    //     Pens for all the standard colors. This class cannot be inherited.
    public sealed class Pens
    {
        public static Pen Transparent { get; }
        public static Pen Orchid { get; }
        public static Pen OrangeRed { get; }
        ...
    }
}

因為密封類不能被繼承,它不能用作基類,因此抽象類不能使用密封修飾符 同樣重要的是要提到結構是隱式密封的

例子

public class BaseClass {
    public virtual string ShowMessage()
    {
        return "Hello world";
    }
    public virtual int MathematicalOperation(int x, int y)
    {
        return x + y;
    }
}
public class DerivedClass : BaseClass {
    public override int MathematicalOperation(int x, int y) 
    {
        // since BaseClass has a method marked as virtual, DerivedClass can override it's behavior
        return x - y;
    }
    public override sealed string ShowMessage()
    {
        // since BaseClass has a method marked as virtual, DerivedClass can override it's behavior but because it's sealed prevent classes that derive from it to override the method
        return "Hello world sealed";
    }
}
public class DerivedDerivedClass : DerivedClass
{
    public override int MathematicalOperation(int x, int y)
    {
        // since BaseClass has a method marked as virtual, DerivedClass can override it's behavior
        return x * y;
    }
    public override  string ShowMessage() { ... } // compile error
}
public sealed class SealedClass: BaseClass {
    public override int MathematicalOperation(int x, int y)
    {
        // since BaseClass has a method marked as virtual, DerivedClass can override it's behavior
        return x * y;
    }
    public override string ShowMessage()
    {
        // since BaseClass has a method marked as virtual, DerivedClass can override it's behavior but because it's sealed prevent classes that derive from it to override the method
        return "Hello world";
    }
}
public class DerivedSealedClass : SealedClass
{
    // compile error
}

微軟文檔

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/sealed

C# 有它是因為 Java 有一個相同的特性( final方法)。 我從未見過合法用途。

如果您不想允許擴展,則應將整個類標記為已sealed ,而不僅僅是一種方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM