前往
大廳
主題

[C#] C# 8.0 介面(Interface)新功能-預設實作

帥氣跳蚤蛋 | 2021-09-12 09:39:10 | 巴幣 110 | 人氣 870

C# 8.0對於介面功能最大的差別,就是可以預設實作介面啦~
傳統介面的缺點,就是在程式發佈後,就無法增加介面方法,
透過預設實作的功能,可更彈性的為已發行的介面進行擴充.

好啦~我知道C# 8.0已經不新了,但因這是C#的新特性,還是來記錄一下~
本功能在C# 8.0 與 .NET Core 3.0以上的版本可供使用.
===========================================================================
先來回憶一下之前的介面寫法,
介面僅能宣告方法但不能實作,而繼承的Class則必須實作全部的介面方法與屬性.
public interface ISample    //宣告介面
{
    int num { get; set; }   //宣告屬性
    string Hello(); //宣告方法
    int World(int n);
}
public class HelloWorld : ISample   //實作介面
{
    public int num { get; set; }    //實作屬性
    public string Hello() => "Hello";   //實作方法
    public int World(int n) => n * 10;
}
===========================================================================
而在C# 8.0後介面可進行實作,也可為介面增加public, protected, private…等存取範圍的修飾詞,
預設實作的介面,若類別在繼承後,需要重新實作介面,則照以前的方式實作介面方法即可.
public interface INewInterface
{
    string s { get; set; }  //宣告屬性
    string StrMethod();   //宣告方法
    public string StrReturn() => "INewInterface.StrReturn()";    //預設實作方法
    public int ImpleMethod() => 666;
}
public class NewClass : INewInterface
{
    public string s { get; set; }   //實作屬性
    public string StrMethod() => "NewClass.StrMethod()";  //實作方法
    //StrReturn()因被介面預設實作,可選擇不進行實作
    public int ImpleMethod() => 777;    //實作ImpleMethod()方法,取代介面的預設實作
}

使用方法與傳統的介面一樣,
物件呼叫方法時,若類別有實作方法,則會優先呼叫實作的方法,
若無則呼叫介面預設實作的方法.
static void Main(string[] args)
{
    INewInterface newInterface = new NewClass();
    newInterface.s = "Test";
    Console.WriteLine(newInterface.s);  //取得NewClass實作的屬性
    Console.WriteLine(newInterface.StrMethod());    //取得NewClass實作的方法
    Console.WriteLine(newInterface.StrReturn());    //取得INewInterface預設實作的方法
    Console.WriteLine(newInterface.ImpleMethod());  //INewInterface有預設實作此方法,但NewClass仍實作此方法
    /* 輸出結果:
     * Test
     * NewClass.StrMethod()
     * INewInterface.StrReturn()
     * 777
     */
}
===========================================================================
在本節將測試在多重繼承介面時,物件呼叫方法的行為,先建立IA,IB兩個介面,擁有相同名稱的MethodA(),並分別預設實作此方法,建立ClassAB類別,繼承IA,IB兩個介面,明確實作IA.MethodA(),與實作MethodA().
public interface IA
{
    public string MethodA() => "IA.MethodA";    //預設實作方法
}
public interface IB
{
    public string MethodA() => "IB.MethodA";    //預設實作方法
}
public class ClassAB : IA, IB
{
    string IA.MethodA() => "ClassAB.IA.MethodA()"; //明確實作IA的MethodB()
    //IB的MethodB不進行實作
    public string MethodA() => "ClassAB.MethodA()";    //實作MethodB()
}

與傳統的介面相同若有明確實作介面的方法,則優先呼叫.
class Program
{
    static void Main(string[] args)
    {
        IA iA = new ClassAB();
        IB iB = new ClassAB();
        ClassAB classAB = new ClassAB();
        Console.WriteLine(iA.MethodA());    //明確實作IA的MethodA()
        Console.WriteLine(iB.MethodA());    //IB無明確實作,所以呼叫實作的MethodA()
        Console.WriteLine(classAB.MethodA());   //呼叫實作的MethodA()
        /* 輸出結果:
         * ClassAB.IA.MethodA()
         * ClassAB.MethodA()
         * ClassAB.MethodA()
         */
    }
}
===========================================================================
本節將測試在多重繼承介面的狀況下,若介面擁有相同名稱的方法,但各方法的回傳值不同,物件呼叫方法的行為,先建立IAA,IBB兩個介面,並擁有相同名稱的MethodB(),但各自擁有不同的Tuple回傳型態,接著建立建立ClassAABB類別,繼承IAA,IBB兩個介面,同時也撰寫與兩介面不同Tuple回傳型態的MethodB().
public interface IAA
{
    public (string str, int num) MethodB() => ("IA.MethodB()", 123);
}
public interface IBB
{
    public (string str, bool boo) MethodB() => ("IB.MethodB()", true);
}
public class ClassAABB : IAA, IBB
{
    public (string str, DateTime date) MethodB() => ("ClassAB.MethodB()", DateTime.Now);
}

即使是相同名稱的方法,若各介面方法參數不同,則仍呼叫各自介面的方法.
class Program
{
    static void Main(string[] args)
    {
        IAA iAA = new ClassAABB();
        IBB iBB = new ClassAABB();
        ClassAABB classAABB = new ClassAABB();
        Console.WriteLine(iAA.MethodB());    //public (string str, int num) MethodB()
        Console.WriteLine(iBB.MethodB());    //public (string str, bool boo) MethodB()
        Console.WriteLine(classAABB.MethodB());   //public (string str, DateTime date) MethodB()
        /* 輸出結果:
         * (IA.MethodB(), 123)
         * (IB.MethodB(), True)
         * (ClassAB.MethodB(), 2021/9/11 下午 11:47:33)
         */
    }
}
===========================================================================
雖然C# 8.0已經出來一段時間了,但本帥就是怕忘記,所以還是紀錄此功能~預設實作功能讓介面的設計有了更大的彈性,對於往後擴充算是一大福音,微軟官方也有提供應用的範例,可讓讀者更了解應用情境:
===========================================================================
本帥的心情抒發(廢文):
今天周六要上班,是為了補9/20的中秋節4天連假,有點累累Der~但是這兩天有颱風來...璨樹颱風居然是禮拜日才來...很哭ㄟ~這禮拜唯一的假日沒了QQ話說放颱風假是2年前的事了~台灣有股神秘力量,讓颱風不敢進來= =
===========================================================================
本文轉載自本帥的部落格:
送禮物贊助創作者 !
0
留言

創作回應

更多創作