接口描述的是可属于任何类或结构的一组相关功能。 接口使用 interface 关键字进行定义,如下面的示例所示。
interface IEquatable<T>
{
bool Equals(T obj);
}
接口可由方法、属性、事件、索引器或这四种成员类型的任意组合构成。 接口不能包含常量、字段、运算符、实例构造函数、析构函数或类型。 它不能包含静态成员。 接口成员是自动公开的,且不能包含任何访问修饰符。
类或结构实现接口时,该类或结构将为该接口定义的所有成员提供实现。 接口本身不提供类或结构能够以继承基类功能的方式继承的任何功能。 但是,如果基类实现接口,派生类将继承该实现。 派生的类被认为是隐式地实现接口。
类和结构按照类继承基类或结构的类似方式实现接口,但有两个例外:
类或结构可实现多个接口。
类或结构实现接口时,仅接收方法名称和签名,因为接口本身不包含实现,如下面的示例所示。
public class Car : IEquatable<Car>
{
public string Make {get; set;}
public string Model { get; set; }
public string Year { get; set; }
// Implementation of IEquatable<T> interface
public bool Equals(Car car)
{
if (this.Make == car.Make &&
this.Model == car.Model &&
this.Year == car.Year)
{
return true;
}
else
return false;
}
}
IEquatable<T> 接口向对象的用户宣布该对象可以确定其是否与同一类型的其他对象相等,而接口的用户不需要知道相关的实现方式。
若要实现接口成员,类中的对应成员必须是公共的、非静态的,并且与接口成员具有相同的名称和签名。 类的属性和索引器可以为接口上定义的属性或索引器定义额外的访问器。 例如,接口可以声明具有 get 取值函数的属性。 实现接口的类可以声明与 获取 和 设置 访问器相同的属性。 但是,如果属性或索引器使用显式实现,则访问器必须匹配。 有关隐式续行符的更多信息,请参见接口属性(C# 编程指南)。
接口和接口成员是抽象的;接口不提供默认实现。 有关更多信息,请参见抽象类、密封类和类成员。
接口可以继承其他接口。 类可以通过其继承的基类或其他接口继承的接口多次继承某个接口。 但是,类只能实现该接口一次,且仅当把该接口声明作为类的一部分时才可以,如 class ClassName : InterfaceName。 如果由于继承了一个实现接口的基类使得接口被继承,则基类会提供其实现。 通过使用虚拟成员,基类可能会实现接口成员。 在这种情况下,派生类可以通过重写虚拟成员来更改接口行为。 有关虚拟成员的更多信息,请参见多态性。
接口概述
接口具有下列属性:
接口类似于抽象基类:实现接口的任何非抽象类型都必须实现接口的所有成员。
不能直接实例化接口。
接口可以包含事件、索引器、方法和属性。
接口不包含方法的实现。
类和结构可继承多个接口。
接口自身可从多个接口继承。
我们来看一个简单的例子:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication13
{
class Program
{
//定义接口,包含两个方法
public interface IPicture
{
int DelImage(int x,int y);
void ShowImage();
}
//类MyPicture继承自类Basel和接口IPicture,要实现接口的所有方法
public class MyPicture : Basel, IPicture
{
public int DelImage(int x, int y)
{
Console.WriteLine("DelImage实现~");
//return (1);
return (x - y);
}
public void ShowImage()
{
Console.WriteLine("ShowImage实现~");
}
}
public class Basel
{
public void Open()
{
Console.WriteLine("Basel的Open方法~");
}
}
static void Main(string[] args)
{
//显式实现接口
MyPicture objM = new MyPicture();
objM.ShowImage();
//objM.DelImage(2,2);
//将返回值赋给t,用控制台程序输出
//假如不输出来,返回值放在哪里?内存?栈区?以后深究
int t = objM.DelImage(2, 2);
Console.WriteLine(t);
objM.Open();
Console.ReadKey();
}
}
}
接口的实现很多人都知道,但接口的实现方式分显示实现和隐示实现不知道是不是很多人知道呢!但我觉的公司技术部里很少提到这个,就想起来写写这篇blogs。
目前常用的方式:
public interface IReview
{
void GetReviews();
}
public class ShopReview :IReview
{
public void GetReviews(){}
}
这种方式是隐示实现:
IReview rv = new ShopReview();rv.GetReviews();
ShopReview rv = new ShopReview();rv.GetReviews();
都可以调用GetReviews这个方法。
还有一种方式是显示实现:
public interface IReview
{
void GetReviews();
}
public class ShopReview :IReview
{
void IReview.GetReviews(){}
}
通过这种方式的接口实现。GetReviews就只能通过接口来调用:
IReview rv = new ShopReview();rv.GetReviews();
下面的这种方式将会编译错误:
ShopReview rv = new ShopReview();rv.GetReviews();
结论:
隐示实现接口和类都可以访问
显示实现只有接口可以访问。
显示实现益处
1:隐藏代码的实现
2:在使用接口访问的系统中,调用者只能通过接口调用而不是底层的类来访问。
显式实现接口
如果类实现两个接口,并且这两个接口包含具有相同签名的成员,那么在类中实现该成员将导致两个接口都使用该成员作为它们的实现。 例如:
interface IControl
{
void Paint();
}
interface ISurface
{
void Paint();
}
class SampleClass : IControl, ISurface
{
// Both ISurface.Paint and IControl.Paint call this method.
public void Paint()
{
}
}
然而,如果两个接口成员执行不同的函数,那么这可能会导致其中一个接口的实现不正确或两个接口的实现都不正确。 可以显式地实现接口成员 -- 即创建一个仅通过该接口调用并且特定于该接口的类成员。 这是使用接口名称和一个句点命名该类成员来实现的。 例如:
public class SampleClass : IControl, ISurface
{
void IControl.Paint()
{
System.Console.WriteLine("IControl.Paint");
}
void ISurface.Paint()
{
System.Console.WriteLine("ISurface.Paint");
}
}
类成员 IControl.Paint 只能通过 IControl 接口使用,ISurface.Paint 只能通过 ISurface 使用。 两个方法实现都是分离的,都不可以直接在类中使用。 例如:
SampleClass obj = new SampleClass();
//obj.Paint(); // Compiler error.
IControl c = (IControl)obj;
c.Paint(); // Calls IControl.Paint on SampleClass.
ISurface s = (ISurface)obj;
s.Paint(); // Calls ISurface.Paint on SampleClass.
显式实现还用于解决两个接口分别声明具有相同名称的不同成员(如属性和方法)的情况:
interface ILeft
{
int P { get;}
}
interface IRight
{
int P();
}
为了同时实现两个接口,类必须对属性 P 和/或方法 P 使用显式实现以避免编译器错误。 例如:
class Middle : ILeft, IRight
{
public int P() { return 0; }
int ILeft.P { get { return 0; } }
}
示例:
多重接口实现
- C# 不允许多重类继承
- 但C#允许多重接口实现,这意味着一个类可以实现多个接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication14
{
class Program
{
public interface IPictManip
{
void ApplyAlpha();
void ShowImage();
}
public interface IPicture
{
int DelImage();
void ShowImage();
}
public class BaseIO
{
public void Open()
{
Console.WriteLine("BaseIO的Open方法");
}
}
public class MyPicture:BaseIO,IPicture,IPictManip
{
public int DelImage()
{
Console.WriteLine("DelImage实现~");
return(1);
}
public void ApplyAlpha()
{
Console.WriteLine("ApplyAlpha实现~");
}
void IPicture.ShowImage()
{
Console.WriteLine("ShowImage的IPicture实现");
}
void IPictManip.ShowImage()
{
Console.WriteLine("ShowImage的IIPictManip实现~");
}
}
static void Main(string[] args)
{
MyPicture objM = new MyPicture();
//IPicture引用
IPicture Pict = objM;
Pict.ShowImage();
//IPictManip引用
IPictManip PictManip = objM;
PictManip.ApplyAlpha();
PictManip.ShowImage();
Console.ReadKey();
}
}
}