GVKun编程网logo

C# Interface:接口(c#中接口)

23

在本文中,我们将详细介绍C#Interface:接口的各个方面,并为您提供关于c#中接口的相关解答,同时,我们也将为您带来关于C#--接口(关键字:interface)、C#接口(Interface)

在本文中,我们将详细介绍C# Interface:接口的各个方面,并为您提供关于c#中接口的相关解答,同时,我们也将为您带来关于C# -- 接口 (关键字:interface)、C# 接口 (Interface)、C# 接口(Interface)、C#中接口(interface)的理解的有用知识。

本文目录一览:

C# Interface:接口(c#中接口)

C# Interface:接口(c#中接口)

C# 的接口可以看成是一个“技能库”,继承一个接口可以看成是“插上一个新的技能库”,它使得你的类型拥有更多的“技能”。

例如,IComparable 使得类型可以比较大小。接口是一种特殊的抽象类,在其中,不能显式地实现方法;也就是说,接口只拥有一组方法的签名。

不过,这个看似已经成为常识的事情在 C# 8 中可能会发生改变:接口也许可以拥有默认方法实现。如果这真的变成了现实,那么,C# 就成了一个允许多重继承的语言。

当然,不是继承了接口就万事大吉的,必须实现接口的方法才可以真正的扩展你的类。例如,必须实现 Compareto,并在其中解释如何比较大小。

接口负责对现实生活中 Has A 关系的描述。例如,可以比较大小明显是某个类拥有(has)的性质或能力,而不是说,某个类是“比较大小”,这在中文上都不通。

接口中的所有方法都是 public 的,也不能再使用其他访问修饰符进行修饰。接口也可以拥有自己的属性、事件和索引器。

显式接口实现

如果两个不同的接口中含有一个相同的方法(相同的名称,参数和返回类型),那么,同时继承这两个接口的类型在实现该方法之后,两个接口的方法就会具有相同的行为:
class Program
{
    static void Main(string[] args)
    {
        var cg = new Greeting();
        var chinese = (ChineseGreeting)cg;
        //你好
        chinese.Hello();

        var english = (EnglishGreeting)cg;
        //你好
        english.Hello();
        Console.ReadKey();
    }
}
public interface ChineseGreeting
{
    void Hello();
}
public interface EnglishGreeting
{
    void Hello();
}
public class Greeting : ChineseGreeting,EnglishGreeting
{
    //隐式接口实现导致方法只有一次实现机会
    //两个接口的Hello将会有相同的行为
    public void Hello()
    {
        Console.Write("你好!");
    }
}
为了区别开不同接口相同方法的实现,我们可以使用显式接口实现:
public class Greeting : ChineseGreeting,EnglishGreeting
{
    //显式接口实现
    void ChineseGreeting.Hello()
    {
        Console.Write("你好!");
    }
    void EnglishGreeting.Hello()
    {
        Console.Write("Hello!");
    }
}
用的方式是相同的。在使用显式接口实现之后,必须将对象转化为接口类型才可以访问它。因为显式接口实现的方法默认是接口类型私有的(也不能使用访问修饰符),而且是 sealed。

下面的代码试图从接口的继承类型调用显式接口实现的方法,这会导致编译错误:

//继承类不存在此方法,显式接口实现方法归接口私有
cg.Hello();

显式接口实现有着诸多缺点,例如必须手动转换类型为接口基类型(如果派生类是值类型,那么还会导致装箱),没有 IDE 智能感知等。

下面是一个 .NET 中的显式接口实现的例子:

int 1=1;
//由于 ToSingle 是显式接口实现,所以必须先转化为接口基类型
var s = ((IConvertible) i).ToSingle(null);

直接在 i 上调用 ToSingle 无法通过编译。我们看看 int 中的相关代码:

float IConvertible.ToSingle(IFormatProvider provider);

ToSingle 签名包含了接口类型 IConvertible,说明了 ToSingle 方法使用了显式接口实现。

显式接口实现与泛型接口

在泛型还没出现的年代,实现一个接口有时是很头疼的。例如,常用的 IComparable 接口中的 Compareto 方法,输入参数是 object。

因此,任何输入都合法,这不仅可能带来装箱,还会在内部重新转化为自己想要的类型时发生错误。

显式接口实现可以在一定程度上避免这个问题:
public class People : IComparable
{
    public string name { get; set; }
    public int age { get; set; }
    //类型安全的Compareto方法
    public int Compareto(People p)
    {
        return p.age >= age ? 1 : -1;
    }
    //为了实现ICompareable,不得不显示接口实现
    int IComparable.Compareto(object obj)
    {
        //obj转化为People类型可能会出现问题
        return Compareto((People)obj);
    }
}
上面的类型中,通过比较年龄来比较 People 类的大小。在接受 object 为参数的 Compareto 方法中,必须强制将 obj 转化为 People 类,而这是类型不安全的。

我们通过自己写一个 Compareto 方法,并令输入为 People 类解决这个问题。

但是自己的 Compareto 方法并不算是 IComparable 的实现,我们还要被迫实现一个 IComparable 规定的 Compareto 方法。

People p = new People();
People q = new People();
q.Compareto(p);
//如果对象是 People 类型,访问不到显式接口实现的 Compareto 方法
//也就不能传入任意类型
q.Compareto(i); //不能通过编译!

//但是可以通过将类型转化为接口基类型
//访问到显式接口实现的 Compareto 方法,传入任意类型
//于是再次失去类型安全性
var q2 = (IComparable) q;
q2.Compareto(i); //可以通过编译!

我们看到,显式接口实现还是不能完全保证类型安全性,当泛型接口出现之后,问题 就解决了:
public class People : IComparable<People>
{
    public string name { get; set; }
    public int age { get; set; }
    //类型安全的Compareto方法
    public int Compareto(People p)
    {
        return p.age >= age ? 1 : -1;
    }
}
继承 IComparable<T> 使得我们不需要再写一个输入参数为 object 的 Compareto 方法,它绝对保证类型安全,而且,由于没有类型转换,也就不存在装箱。

抽象类 VS 接口

接口和抽象类有一些区别,接口是一种特殊的抽象类:
  • 接口不能有非抽象的方法。而抽象类可以有非抽象的方法。
  • 接口和抽象类都不能被实例化。
  • 如果继承接口,必须实现接口所有的抽象方法。而继承抽象类的类可以只实现一部分父类的抽象方法。
  • 一个类可以继承多个接口,但只能继承自一个别的类。
  • 不能密封抽象类和接口,因为这破坏了接口和抽象类本身的性质,即被人继承。

抽象类和它的子类之间应该是一般和特殊的关系,而接口仅仅是它的子类应该实现的一组规则。当逻辑为一般和特殊的关系,而特殊本身无法或无需有任何方法的实现时,则考虑使用抽象类。

当逻辑为“能做什么”时,使用接口。这样的例子太多了,例如 C# 中所有的数据结构都继承接口 IEnumerable,意味着所有的数据结构都拥有枚举的能力。

另外,如果你的类型继承了接口 Idisposable,则拥有 dispose 的能力。

如果基类型发生变化(例如添加了方法),那么派生类型将自动继承该方法,不需要更改代码。

但如果接口添加了方法,那么所有派生类型都必须更改代码才能通过编译。在这种情形之下,要不就老老实也改代码,要不就考虑将新方法做成一个新的接口。

接口不继承自 Object

接口不继承自任何类型,它旨在提供一个干净的方法库和固定的签名,并等待继承者来实现。

如果接口继承自 Object,那么它就会具有 Object 的方法了。但是,任何类型其实都已经继承了 Object,所以类型再继举一个继承了 Object 方法的接口,就会导致毫无意义的重复。

接口方法分派

假设有一个接口 ITest,含有方法A,—个类型 B 继承了该接口,并实现了 B.A,那么,实际上 B.A 是被 IL 的 newslot+virtual 修饰的(显式接口实现的话,则再加一个 final 关键字)。

因此,可以在类型 B 的方法表中找到 B.A,然后进行调用。而相对的,虽然接口 ITest 是类型 B 的父类,而且方法 A 隐式的为 virtual,接口方法 ITest.A 是不会出现在类型 B 的方法表中的。

C# -- 接口 (关键字:interface)

C# -- 接口 (关键字:interface)

C#: 接口(关键字:interface)

1.代码(入门举例)

Main( Console.WriteLine( IIntroduce iSE = Console.WriteLine( IIntroduce iTc = Console.WriteLine( Console.WriteLine( Console.WriteLine( Console.WriteLine( Console.WriteLine( Console.WriteLine( }

2. 运行结果:

C# 接口 (Interface)

C# 接口 (Interface)

继承 "基类" 跟继承 "接口" 都能实现某些相同的功能,但有些接口能够完成的功能是只用基类无法实现的

1. 接口用于描述一组类的公共方法 / 公共属性。它不实现任何的方法或属性,只是告诉继承它的类至少要实现哪些功能,继承它的类可以增加自己的方法.

2. 使用接口可以使继承它的类:命名统一 / 规范,易于维护。比如:两个类 "狗" 和 "猫", 如果它们都继承了接口 "动物", 其中动物里面有个方法 Behavior (), 那么狗和猫必须得实现 Behavior () 方法,

并且都命名为 Behavior 这样就不会出现命名太杂乱的现象。如果命名不是 Behavior (),接口会约束即不按接口约束命名编译不会通过.

3. 提供永远的接口。 当类增加时,现有接口方法能够满足继承类中的大多数方法,没必要重新给新类设计一组方法,也节省了代码,提高了开发效率.

举个代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//公共接口: "动物"
public  Interface IAnimal
{
int  EyeNumber;
private  void  Behavior(); //行为方法,描述各种动物的特性
}
//类: 狗
public  Dog : IAnimal
{
string  ActiveTime =  "白天" ;
private  void  Behavior()
{
{
Console.Write( "我晚上睡觉,白天活动" );
}
}
//类: 猫
public  Cat: IAnimal
{
string  ActiveTime =  "夜晚" ;
private  void  Behavior()
{ {
Console.Write( "我白天睡觉,晚上活动" );
}
}
//简单的应用:
public  static  Main()
{
Dog myDog =  new  Dog();
myDog.Behavior();  //输出: "我晚上睡觉,白天活动"
Cat myCat =  new  Cat();
myCat.Behavior();  //输出: "我白天睡觉,晚上活动"
}

以上调用不同的类的相同名方法,会输出不同的东东,也就是说每个类里面的同名方法完成的功能可以是完全不同的.

更进一步,不是用上面 Main 方法这样一个一个调用类的方法,用多态性实现其调用.
看一下下面这个方法:

1
2
3
4
public  Behavior(IAnimal myIanimal)
{
myIanimal.Behavior();
}

其参数是 <<接口类型>>,任何继承它的类都可以调用此方法,此方法能根据类的不同调用不同的类中的方法。也即能够自己根据不同的类,完成不同的类的功能.

多态性代码示例: 

1
2
3
4
Dog myDog =  new  Dog();
Cat myCat =  new  Cat();
Behavior(myDog);  //Behavior接受“狗”类实例
Behavior(myCat);  //Behavior接受“狗”类实例

这样 Behavior 方法写一次就能完成所有继承它的类中的相同名方法的不同功能。非常方便,同样,由于 “动物软件” 功能需求,需要再增加一个 "龟" 类:

1
2
3
4
5
6
7
8
9
10
//类: 龟
public  Tortoise: IAnimal
{
string  ActiveTime =  "很难说" ;
private  void  Behavior()
{
{
Console.Write( "我可以不活动,一睡就睡五千年!" );
}
}

那么也可以调用上面多态方法,所以说接口使方法具有较好扩展性.
如果继承它的类很多的话,有多少好处是可想而知的!

另外,也有抽象类能够实现但接口不能实现的情况:

1. 在抽象类中可以加代码逻辑,但接口不能.

2. 如果要在接口中增加一个方法,所有实现它的类都强制重载一遍此方法,如果重载类很多时,会增大工作量.

总之,一般在仅实现单继承用途时,尽量用抽象类,功能也更强些!

C# 接口(Interface)

C# 接口(Interface)

接口定义了所有类继承接口时应遵循的语法合同。接口定义了语法合同 "是什么" 部分,派生类定义了语法合同 "怎么做" 部分。

接口定义了属性、方法和事件,这些都是接口的成员。接口只包含了成员的声明。成员的定义是派生类的责任。接口提供了派生类应遵循的标准结构。

接口使得实现接口的类或结构在形式上保持一致。

抽象类在某种程度上与接口类似,但是,它们大多只是用在当只有少数方法由基类声明由派生类实现时。


定义接口: MyInterface.cs

接口使用 interface 关键字声明,它与类的声明类似。接口声明默认是 public 的。下面是一个接口声明的实例:

 

interface IMyInterface{ void MethodToImplement();}

  

以上代码定义了接口 IMyInterface。通常接口命令以 I 字母开头,这个接口只有一个方法 MethodToImplement (),没有参数和返回值,当然我们可以按照需求设置参数和返回值。

值得注意的是,该方法并没有具体的实现。

接下来我们来实现以上接口:InterfaceImplementer.cs

实例

using System;interface IMyInterface{  // 接口成员 void MethodToImplement();}class InterfaceImplementer : IMyInterface{ static void Main() {  InterfaceImplementer iImp = new InterfaceImplementer();  iImp.MethodToImplement(); } public void MethodToImplement() {  Console.WriteLine("MethodToImplement() called."); }}

  InterfaceImplementer 类实现了 IMyInterface 接口,接口的实现与类的继承语法格式类似:

class InterfaceImplementer : IMyInterface

  

继承接口后,我们需要实现接口的方法 MethodToImplement () , 方法名必须与接口定义的方法名一致.........

C#中接口(interface)的理解

C#中接口(interface)的理解

.都是“虚的”不能被实例化,这也是接口中为什么不能包含字段--成员变量的原因。
  2.正因为接口是虚的,所以接口内的索引,属性,时间等只能有声明,而不能在接口内实现,具体如何实现是派生接口或者派生类的事。
  3.都具有模板的性质,如果一个接口或者类从某一个接口继承,它将自动具有被集成者的特征(包括索引,函数,实践等)。
  4.接口支持多重继承,而C#中,类之支持单一继承,接口实际表示的是一种承载能力。
下面是接口的一个简单定义:
复制代码 代码如下:

interface 
SampInterface1 

    string  
    this[ int index] 
    { 
        get; 
        set 
    } 

    event EventHandler Event; 
    void  Find( int value ); 
    //注意此处没有 
    { 
    } 
    string Po 
    int 
    { 
        get; 
        set 
    } 



上面的接口定义了一个索引this,一个实践Event,一个方法Find和一个属性Point.
复制代码 代码如下:

public interface SampIneterface:SampIneterface1{  
pravite  int a=1; 
void find (int value) 

a+=value; 

event EventHandler Event; 
protected void onEvent() 

if(Event=null) 
{return Event(this.System.EventAgrs.Empty;)} 

}

关于C# Interface:接口c#中接口的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于C# -- 接口 (关键字:interface)、C# 接口 (Interface)、C# 接口(Interface)、C#中接口(interface)的理解等相关知识的信息别忘了在本站进行查找喔。

本文标签:

上一篇[TypeScript] Infer the Return Type of a Generic Function Type Parameter

下一篇C#/.NET CLI:公共语言基础设施(c#语言的公共语言运行时简称为)