接口,隐式实现,显式实现介绍

我被代码海扁 @codebeatme-s @103466775
阅读 6:01·字数 1810·发布 

接口

接口是一种设计约定,主要针对类,用于规定其需要实现或具有的成员,在一些语言中,比如 C#,接口也适用于结构。当目标符合接口的约定时,可认为目标实现了接口,一个类可以实现多个接口,一个接口可以被多个类实现。

选择接口还是抽象类?
你需要根据情况来决定是使用接口还是抽象类,这可以从接口和类看待问题的角度说起,类侧重于以事物为中心,大多数类都会代表一种现实或抽象的事物,而接口侧重于以作用为中心,他体现了某种特定的作用或效果,并不关注背后的事物。

比如,某个函数希望调用方传递的实参具有存储功能,此时选择抽象类会遇到问题,因为你的存储类可能继承自其他类,在多重继承不被允许的情况下,这成为了一个小麻烦。

类的多态性
想要了解抽象类,你可以查看方法重写一段。

在下面的 C# 代码中,函数Go的参数movable的类型为接口IMovable,该接口表示一种可移动的效果。类Car实现了接口IMovable,因此,实例car可作为实参传递给函数Go

*.cs
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被隐式实现。

interfaces.cs
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,我们通过显式的方式分别实现了他们。

interfaces.cs
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是接口的一个默认方法。

interfaces.cs
// 接口 IMovable,表示可移动
interface IMovable
{
	// …
	// 方法 Move,表示移动一次
	public void Move()
	{
		// 默认实现为,按照速度调整当前位置
		Location += Speed;
	}
}

接口的继承

和类一样,接口也拥有继承这一特点,被继承的接口被称为基接口或父接口,而继承自基接口的接口,被称为派生接口或子接口。

接口的继承和类的继承之间的区别
类包含了具体实现,继承中的不同类对同一成员的实现是需要加以区分的,接口通常仅包含约定,继承中同一约定多次出现及其归属问题对接口作用的影响不大。

什么是接口的多重继承?
接口的多重继承是指派生接口从多个基接口继承的行为,与类的多重继承不同,接口的多重继承是被普遍支持的。因为多义性的问题,在接口中是不存在或被忽略的。

面向对象
想要详细了解类的继承,多重继承,你可以查看类的继承一段。

下面的 C# 接口IDrivable多重继承自IMovableIRotatable

interfaces.cs
// 接口 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 { }

源码

interfaces.cs·codebeatme/programming·GitHub