C#中接口的顯式實(shí)現(xiàn)與隱式實(shí)現(xiàn)及其相關(guān)應(yīng)用案例詳解
C#中接口的顯式實(shí)現(xiàn)與隱式實(shí)現(xiàn)
最近在學(xué)習(xí)演化一款游戲項(xiàng)目框架時(shí)候,框架作者巧妙使用接口中方法的顯式實(shí)現(xiàn)來變相對(duì)接口中方法進(jìn)行“密封”,增加實(shí)現(xiàn)接口的類訪問方法的“成本”。
接口的顯式實(shí)現(xiàn)和隱式實(shí)現(xiàn):
先定義一個(gè)接口,接口中有這兩個(gè)方法。
public interface ICanSingSong
{
void SingJayChow();
void SingOther();
}接下來我們讓InterfaceDesignExample 繼承該接口。使用常用的隱式實(shí)現(xiàn)方法來實(shí)現(xiàn)SingJayChow方法,在Start函數(shù)中直接可以調(diào)用,而使用顯式實(shí)現(xiàn)的接口方法SingOther,則需要將類的實(shí)力轉(zhuǎn)換為接口類型才可以調(diào)用。
這樣相當(dāng)于告訴類,ICanSingSong.SingOther()樣式就是表明SIngOther是屬于ICanSingSong接口中的“私有方法”。調(diào)用時(shí)候先要將類類型轉(zhuǎn)換為接口。
public class InterfaceDesignExample : MonoBehaviour,ICanSingSong
{
void Start()
{
//接口的隱式實(shí)現(xiàn) 可以直接調(diào)用
SingJayChow();
//顯示調(diào)用則需要 準(zhǔn)換成接口 調(diào)用
//this.SingOther();
(this as ICanSingSong).SingOther();
}
/// <summary>
/// 接口的隱式實(shí)現(xiàn)
/// </summary>
public void SingJayChow()
{
Debug.Log("你說家是唯一的城堡,隨著稻香一路奔跑~");
}
/// <summary>
/// 接口的顯式實(shí)現(xiàn)
/// </summary>
void ICanSingSong.SingOther()
{
Debug.Log("lalalalalalallalaal!");
}
}
我們這樣做的目的之一就是為了增加類對(duì)接口中的一些方法的調(diào)用成本,和使用“private”修飾有類似效果,降低對(duì)方法亂用的可能。
接口-抽象類-子類 使用顯式實(shí)現(xiàn)接口方法
同樣,我們先聲明一個(gè)接口:
//接口 Application
public interface IApplication
{
void Start();
void Update();
void Destroy();
void Test();
}抽象類繼承該接口,并對(duì)生命周期函數(shù)進(jìn)行顯式實(shí)現(xiàn),而供子類繼承實(shí)現(xiàn)的方法為OnXXX
//抽象類
public abstract class Application : IApplication
{
//不希望子類去訪問實(shí)現(xiàn)接口的方法
//使用顯式調(diào)用
void IApplication.Start()
{
OnStart();
}
void IApplication.Update()
{
OnUpdate();
}
void IApplication.Destroy()
{
OnDestroy();
}
public void Test()
{
Debug.Log("我是測(cè)試方法,隱式實(shí)現(xiàn)接口的方法,子類可以輕松訪問我");
}
//希望子類的實(shí)現(xiàn)的方法
public abstract void OnStart();
public abstract void OnUpdate();
public abstract void OnDestroy();
}繼承抽象類的子類對(duì)生命周期函數(shù)進(jìn)行實(shí)現(xiàn):
//子類
public class SubApplication : Application
{
public override void OnStart()
{
Test();
//Start(); 情況會(huì)發(fā)生遞歸調(diào)用 造成堆棧溢出 而此方法使用現(xiàn)實(shí)實(shí)現(xiàn) 所以在子類中無法訪問 避免情況發(fā)生
Debug.Log("OnStart");
}
public override void OnUpdate()
{
Debug.Log("OnUpdate");
}
public override void OnDestroy()
{
Debug.Log("OnDestroy");
}
}最后我們調(diào)用函數(shù):
//測(cè)試調(diào)用 //通過接口調(diào)用 顯示實(shí)現(xiàn)的方法 IApplication application = new SubApplication(); application.Start(); application.Update(); application.Destroy(); //通過類 無法調(diào)用顯示實(shí)現(xiàn)的方法 只能訪問使用OnXXXX方法 Application application2 = new SubApplication(); application2.OnStart(); application2.OnUpdate(); application2.OnDestroy();

這樣我們可以體會(huì)到接口作為高抽象層的存在,可以調(diào)用子類具體實(shí)現(xiàn)的生命周期函數(shù),而子類卻無法訪問顯示實(shí)現(xiàn)的接口中“私有”的生命周期函數(shù)。
接口--子接口--靜態(tài)類拓展 實(shí)現(xiàn)對(duì)接口函數(shù)的訪問修飾
咳咳~故事開始!
作為一個(gè)資深Jay迷,我同樣認(rèn)識(shí)一個(gè)自稱曲庫的小精靈【SongLibrary】,它最拿手的三首歌曲是晴天、彩虹和說好不哭.
//曲庫
public class SongLibrary
{
public void SingSunny()
{
Debug.Log("晴天:刮風(fēng)這天,我試著握你的手~");
}
//彩虹
public void SingRainbow()
{
Debug.Log("彩虹:你要離開,我知道很簡單~");
}
public void SingNoCry()
{
Debug.Log("說好不哭:說好不哭讓我走~");
}
}這個(gè)小曲庫精靈居住在抽象出的留聲機(jī)中,我可以通過留聲機(jī)來和它交流播放對(duì)應(yīng)的歌曲。
public interface ISingAllSong
{
SongLibrary songLibrary { get; }
}留聲機(jī)上有三個(gè)按鈕,對(duì)應(yīng)播放歌曲,
播放晴天的按鈕功能:
抽象出子接口來繼承曲庫接口,通過靜態(tài)類拓展來調(diào)用曲庫中對(duì)應(yīng)方法播放歌曲。
public interface ISingSunny : ISingAllSong
{
}
//靜態(tài)類拓展
public static class SingSunnyExtensions
{
public static void SingSunny(this ISingSunny self)
{
self.songLibrary.SingSunny();
}
}同樣的方式,兩個(gè)子接口。兩個(gè)繼承子接口的靜態(tài)類負(fù)責(zé)調(diào)用曲庫中的方法:
//彩虹
public interface ISingRainbow : ISingAllSong
{
}
//靜態(tài)類拓展
public static class SingRainbowExtensions
{
public static void SingRainbow(this ISingRainbow self)
{
self.songLibrary.SingRainbow();
}
}
//說好不哭
public interface ISingNoCry : ISingAllSong
{
}
//靜態(tài)類拓展
public static class SingNoCryExtensions
{
public static void SingNoCry(this ISingNoCry self)
{
self.songLibrary.SingNoCry();
}
}這樣我們使用三個(gè)靜態(tài)類來調(diào)用留聲機(jī)【interface】中居住的精靈【class】的方法,實(shí)現(xiàn)三個(gè)按鈕功能。
當(dāng)我想聽歌時(shí)候,我只需要按照我的需求,搭配繼承對(duì)應(yīng)的子接口即可播放對(duì)應(yīng)的歌曲,不用怕我按下去的是晴天歌曲播放按鈕而短路到播放其它的歌曲曲目。
這樣保證,拿到對(duì)應(yīng)的子按鈕,只能播放對(duì)應(yīng)的歌曲,保證曲目播放的有序性。
public class InterfaceRuleExample : MonoBehaviour
{
public class OnlySingSunny : ISingSunny
{
SongLibrary ISingAllSong.songLibrary { get; } = new SongLibrary();
}
public class OnlySingRainbowNoCry : ISingRainbow,ISingNoCry
{
SongLibrary ISingAllSong.songLibrary { get; } = new SongLibrary();
}
void Start()
{
var onlySingSunny = new OnlySingSunny();
onlySingSunny.SingSunny();
//不能訪問
//onlySingSunny.SingRainbow()
//onlySingSunny.SingNoCry();
var SingRainbowNoCry = new OnlySingRainbowNoCry();
SingRainbowNoCry.SingRainbow();
SingRainbowNoCry.SingNoCry();
//無法訪問
//SingRainbowNoCry.SingSUnny();
}
}
總結(jié)一下:
使用顯示實(shí)現(xiàn)方式來對(duì)接口中方法進(jìn)行實(shí)現(xiàn),子類是無法直接調(diào)用的,需要將類轉(zhuǎn)換為接口類型才可以調(diào)用。
同時(shí)如果接口中的方法不想讓子類直接調(diào)用,可以讓抽象類繼承接口原生方法,在抽象類中進(jìn)行方法聲明供子類調(diào)用,避免子類對(duì)抽象層的直接交互。同時(shí),使用靜態(tài)類拓展來限制子接口對(duì)父接口中存在函數(shù)方法的訪問,保證類對(duì)所需方法的規(guī)范使用。
也就是說,盡可能不讓表層具象的類輕松的訪問到抽象層的其它不需要的功能,即類需要什么就繼承對(duì)應(yīng)的子接口,實(shí)現(xiàn)對(duì)應(yīng)功能即可,多余的功能不要訪問。
當(dāng)然也建議閱讀一下官方社區(qū)對(duì)顯式接口的實(shí)現(xiàn)的解釋說明。
參考文章:
顯式接口實(shí)現(xiàn) - C# | Microsoft Learn
到此這篇關(guān)于C#中接口的顯式實(shí)現(xiàn)與隱式實(shí)現(xiàn)及其相關(guān)應(yīng)用案例的文章就介紹到這了,更多相關(guān)C#中接口的顯式實(shí)現(xiàn)與隱式實(shí)現(xiàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#代碼實(shí)現(xiàn)打印Excel文檔的超詳細(xì)教程
在?.NET?環(huán)境中實(shí)現(xiàn)高質(zhì)量的?Excel?打印并非易事,本文將帶大家使用?Spire.XLS?for?.NET?結(jié)合?System.Drawing.Printing?命名空間,構(gòu)建完整的?Excel?打印解決方案,希望對(duì)大家有所幫助2026-05-05
12306奇葩驗(yàn)證碼引發(fā)思考之C#實(shí)現(xiàn)驗(yàn)證碼程序
春運(yùn)最高峰來了!明天通過網(wǎng)絡(luò)將能買到小年夜的車票,本周四就將開售除夕日車票,但不少人被首次在春運(yùn)期間使用的圖片驗(yàn)證碼搞得很火大,小編也正在對(duì)驗(yàn)證碼進(jìn)行研究,編寫了由C#實(shí)現(xiàn)驗(yàn)證碼程序,分享給大家2015-12-12
c#使用linq技術(shù)創(chuàng)建xml文件的小例子
c#使用linq技術(shù)創(chuàng)建xml文件的小例子,需要的朋友可以參考一下2013-03-03
使用C#實(shí)現(xiàn)一個(gè)網(wǎng)絡(luò)文件傳輸工具
在企業(yè)級(jí)開發(fā)中,文件傳輸功能幾乎是必備需求,無論是內(nèi)網(wǎng)文件同步、遠(yuǎn)程數(shù)據(jù)備份,還是分布式系統(tǒng)間的文件交換,一個(gè)穩(wěn)定高效的文件傳輸工具都顯得至關(guān)重要,今天我們就來徹底搞定這個(gè)問題,用 C# 打造一個(gè)功能專一、穩(wěn)定可靠的網(wǎng)絡(luò)文件傳輸工具,需要的朋友可以參考下2025-12-12
基于C#實(shí)現(xiàn)一個(gè)流程圖工具的代碼示例
軟件開發(fā)中,流程圖作為可視化業(yè)務(wù)邏輯的核心工具,其重要性不言而喻,然而,市面上的專業(yè)流程圖工具往往功能冗余、學(xué)習(xí)成本高,而輕量級(jí)解決方案又難以滿足定制化需求,本文將通過一個(gè)完整的WinForm流程圖編輯器實(shí)現(xiàn)案例,講解如何用C#開發(fā)一個(gè)功能完備的圖形化工具2025-09-09
C#使用IronPython庫調(diào)用Python腳本
這篇文章介紹了C#使用IronPython庫調(diào)用Python腳本的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06
C#監(jiān)聽txt文檔獲取新數(shù)據(jù)方式
文章介紹通過監(jiān)聽txt文件獲取最新數(shù)據(jù),并實(shí)現(xiàn)開機(jī)自啟動(dòng)、禁用窗口關(guān)閉按鈕、阻止Ctrl+C中斷及防止程序退出等功能,代碼整合于主函數(shù)中,供參考學(xué)習(xí)2025-07-07
Unity實(shí)現(xiàn)卡牌翻動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)卡牌翻動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02
Unity?UGUI的StandaloneInputModule標(biāo)準(zhǔn)輸入模塊組件使用示例
這篇文章主要為大家介紹了Unity?UGUI的StandaloneInputModule標(biāo)準(zhǔn)輸入模塊組件使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08

