介面,隱含實作,明確實作介紹
訂閱 375
介面
介面是一種設計約定,主要針對類別,用於規定其需要實作或具有的成員,在一些語言中,比如 C#,介面也適用於結構。當目標符合介面的約定時,可認為目標實作了介面,一個類別可以實作多個介面,一個介面可以被多個類別實作。
選擇介面還是抽象類別?
你需要根據情況來決定是使用介面還是抽象類別,這可以從介面和類別看待問題的角度說起,類別側重於以事物為中心,大多數類別都會代表一種現實或抽象的事物,而介面側重於以作用為中心,他體現了某種特定的作用或效果,並不關註背後的事物。
比如,某個函式希望呼叫方傳遞的引數具有儲存功能,此時選擇抽象類別會遇到問題,因為你的儲存類別可能繼承自其他類別,在多重繼承不被允許的情況下,這成為了一個小麻煩。
類別的多型
想要了解抽象類別,你可以檢視方法覆寫一段。
在下面的 C# 程式碼中,函式Go
的參數movable
的型別為介面IMovable
,該介面表示一種可移動的效果。類別Car
實作了介面IMovable
,因此,執行個體car
可作為引數傳遞給函式Go
。
using System.Numerics;
// 函式 Go,用來移動一個可移動的目標
void Go(IMovable movable)
{
// 如果速度為 0,則不需要移動
if (movable.Speed == Vector2.Zero) {
Console.WriteLine("目前速度為 0?拋錨了?");
return;
}
// 移動並顯示位置
movable.Move();
Console.WriteLine($"移動後的位置:{movable.Speed}");
}
// 建立 Car 的執行個體
Car car = new()
{
// 設定移動速度
Speed = new Vector2(1.5f, 2.5f)
};
// 呼叫 Go 方法進行移動
Go(car);
移動後的位置:<1.5, 2.5>
介面的隱含實作
介面的隱含實作,並不要求將成員明確的宣告為介面的實作,雖然該成員起到了這樣的作用。當隱含實作介面所約定的成員時,這些成員一般可通過類別的執行個體或介面的執行個體來存取。
在 C# 類別Car
中,介面IMovable
的成員Speed
被隱含實作。
using System.Numerics;
// 介面 IMovable,表示可移動
interface IMovable
{
// …
// 屬性 Speed,表示移動速度
public Vector2 Speed { get; set; }
// …
}
// 類別 Car
class Car : IMovable
{
// …
// 隱含實作了 IMovable 介面的成員 Speed
public Vector2 Speed { get; set; }
}
介面的明確實作
介面的明確實作,要求類別的成員明確宣告為介面的實作,當明確實作介面所約定的成員時,這些成員一般只能通過介面執行個體存取。
為何需要明確實作?
通過明確實作,類別可以明確針對某個介面的某個成員,這在兩個或更多介面具有同名成員,而你希望為他們編寫各自的實作時,是有效的。
下面,為類別Car
實作另一個介面IEMailable
,該介面與IMovable
均宣告了成員Location
,我們通過明確的方式分別實作了他們。
using System.Numerics;
// 介面 IMovable,表示可移動
interface IMovable
{
// 屬性 Location,表示目前位置
public Vector2 Location { get; set; }
// …
}
// 介面 IEMailable,表示可投遞電子郵件
interface IEMailable
{
// 屬性 Location,表示電子郵件的位址
public string Location { get; set; }
}
// 類別 Car
class Car : IMovable, IEMailable
{
// 明確實作了 IMovable 介面的成員 Location
Vector2 IMovable.Location { get; set; }
// 明確實作了 IEMailable 介面的成員 Location
// 好吧,這是預約該車的方式
string IEMailable.Location { get; set; } = string.Empty;
// …
}
介面的預設方法
介面的預設方法,是指介面宣告的具有預設實作的方法,由於已經被實作,需要實作介面的目標可以忽略這些方法。
介面IMovable
宣告的方法Move
具有預設實作,因此,Move
是介面的一個預設方法。
// 介面 IMovable,表示可移動
interface IMovable
{
// …
// 方法 Move,表示移動一次
public void Move()
{
// 預設實作為,按照速度調整目前位置
Location += Speed;
}
}
介面的繼承
和類別一樣,介面也擁有繼承這一特性,被繼承的介面被稱為基礎介面或父介面,而繼承自基礎介面的介面,被稱為衍生介面或子介面。
介面的繼承和類別的繼承之間的區別
類別包含了具體實作,繼承中的不同類別對同一成員的實作是需要加以區分的,介面通常僅包含約定,繼承中同一約定多次出現及其歸屬問題對介面作用的影響不大。
什麽是介面的多重繼承?
介面的多重繼承是指衍生介面從多個基礎介面繼承的行為,與類別的多重繼承不同,介面的多重繼承是被普遍支援的。因為多義性的問題,在介面中是不存在或被忽略的。
物件導向
想要詳細了解類別的繼承,多重繼承,你可以檢視類別的繼承一段。
下面的 C# 介面IDrivable
多重繼承自IMovable
和IRotatable
。
// 介面 IMovable,表示可旋轉
interface IRotatable
{
// 屬性 Angle,表示目前角度
public float Angle { get; set; }
// 屬性 Speed,表示旋轉速度
public float Speed { get; set; }
// 方法 Rotate,表示旋轉一次
public void Rotate()
{
// 預設實作為,按照速度旋轉目前角度
Angle += Speed;
}
}
// 介面 IMovable,表示可駕駛
interface IDrivable : IMovable, IRotatable { }