# c#基础系列之C# 接口(interface)

c#基础系列之C# 接口(interface)

接口定义

Public interface IAnimals{
    void eat();
}

tips:接口命名以“I”开头

接口只提供给类定义,但不提供其实现,与类有所不同

  • 接口中的成员只能是隐含抽象的,而类包含抽象与具体实现的成员
  • 一个类可以实现多个接口,但只能继承一个类
  • 接口成员总是隐式定义为Public,不可以用其他访问修饰符声明,实现接口意味着为其他成员提供所有public实现

接口用法

  • 可以把对象隐式或显式转换为他实现的任意一个接口
  • 如果继承接口的是被 internal 修饰的类,那么可以将类的实例转换成接口类型,那么其内部实现的接口成员可以作为public成员访问
  • 继承并实现接口方法的类,在其主函数中不能直接使用已实现的接口的成员方法,需要定义该接口类型的变量然后获取继承自该接口的类的实例,通过该变量调用已经实现的方法。
  • 接口中不能定义字段,但可以定义属性!!!!
 public interface IEnumeratora
    {
        bool MoveNext();
        object Current { get; }
        void reset();
    }

    internal class Countdown : IEnumeratora
    {
        int count = 11;
        public bool MoveNext()
        {
            return count-- > 0;
        }

        public object Current
        {
            get
            {
                return count;
            }
        }

        public void reset()
        {
            count = 11;
        }
    }
 static void Main(string[] args)
        {

            IEnumeratora e = new Countdown();
            do
            {
                Console.WriteLine(e.Current);
            } while (e.MoveNext());

            Console.ReadKey();
        }

结果
这里写图片描述


扩展接口

接口可以从及其他接口派生

public interface A{
void a();
}

public interface B:A{
void b();
}
  • B继承A中的所有成员,实现B必须实现A中的成员

显式与隐式接口实现

  • 什么是显式与隐式实现接口
public interface IAnimals{
void eat()
}
//这就是显式
public class Bird :IAnimals{
void IAnimals.eat(){
Console.WriteLine("Bird.eat");
}
}
//这就是隐式
public class Bird1 :IAnimals{
public void eat(){
Console.WriteLine("Bird1.eat");
}
}

tips:隐式实现接口需要用public等修饰符修饰

  • 当实现多个接口时,如果接口成员标识符出现重复那么,便可以用显式实现接口的方式来避免错误
  • 需要隐藏和正常类使用差别很大的或是干扰性特别强的成员时,需要以显式实现的的方式来避免错误
public interface IAnimals{
void eat()
}

public interface IPerson{
void eat()
}
public class people : IPerson ,IAnimals{
    void IAnimals.eat(){
    Console.WriteLine("IAnimals.eat");
}
void IPerson .eat(){
    Console.WriteLine("IPerson .eat");
}
}
  • 调用显式实现的接口的唯一办法是先将类的实例转换为相应的接口
People peo = new People();
((IPerson)peo).eat();
  • 在默认情况下接口成员是隐式实现的,需要使用virtual或是abstract来达到在派生类中重写该成员方法
public interface IPerson{
void eat();
}

public class People : IPerson{
    public virtual void eat(){
    Console.WriteLine("People.eat");
}

}

public class Zach : People{
public override void eat(){
    Console.WriteLine("Zach.eat");
}
}
Zach zachy = new Zach();
zachy.eat();        //Zach.eat
((IPerson)zachy).eat(); //Zach.eat
((People)zachy).eat(); //Zach.eat
  • 不管是从接口还是基类中调用的成员方法,调用的都是子类的实现
  • 显式实现借口成员并不能标识为virtual,所以 显式实现接口的基类 并不能被 继承自它的派生类 重写,但却可以重新实现

在子类重新实现接口

  • 子类可以重新实现基类已经实现的任一接口,并且可以屏蔽基类中实现的成员方法
public interface IAnimals{ void eat(); }

public class Animals : IAnimals{
    public void IAnimals.eat(){
    Console.WriteLine("Animals.eat");
}
}

public class Bird : Animals,IAnimals{
public new void eat(){
Console.WriteLine("Bird.eat");
}
}

-从接口中调用成员时,调用的是子类的实现

Bird b = new Bird();
b.eat(); //Bird.eat
((IAnimals)b).eat(); //Bird.eat

-假定Bird类不变,将Animals类中的显式实现改成隐式实现,那么会变成这样

Bird b = new Bird();
b.eat(); //Bird.eat
((IAnimals)b).eat(); //Bird.eat
((Animals)b).eat() //Animals.eat
  • 即使在显式实现中,接口依然会出现问题
    • 子类无法调用基类的方法
    • 基类无法判断子类是否需要重新实现基类方法
  • 于是可以使用其他方式替代子类重新实现

接口的替代重新实现的方式

  • 当隐式实现接口成员时,可以的话将其标注为virtual
  • 如果可以预测子类需要重写某些逻辑,可以用这种方法去完成重新实现的功能‘
public class Animals : IAnimals{
void IAnimals.eat(){ eat();}
public virtual void eat(){
Console.WriteLine("Animals.eat");
}
}
public class Bird : Animals{
publicoverride void eat(){
Console.WriteLine("Bird .eat");
}
}

类和接口的对比(什么情况下写类,什么情况下写接口)

  • 当能够自然的共享实现时,使用类和子类
  • 当实现是独立的时候,使用接口

    • 举个栗子

    所有的鸟都可以共享鸟的这一个标签,但所有的鸟并不能共享食肉动物这个标签
    所有的虫子可以共享虫这一个标签,但并不能共享食肉这个标签
    食肉是鸟或虫子里部分个体的标签,就说食肉是独立的
    而,鸟/虫子是共享的


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值