c#:浅析接口(interface)

c#:浅析接口(interface)


c#接口是一个让很多c#初学者容易迷糊的东西,但是它有什么用处呢?如何使用呢?来让我们一起来谈谈究竟吧!

1、什么是接口

​ (1)接口定义了所有类继承接口时应遵循的语法合同。接口定义了语法合同 “是什么” 部分,派生类定义了语法合同 “怎么做” 部分。其实,接口简单理解就是一种约定,使得实现接口的类或结构在形式上保持一致。

①是什么部分:

​ 接口只包含了成员的声明。也就是说接口只声明,类或结构一旦继承,那么就要按照结构声明的东西,重写接口中的所有数据,这就像是遵循了某种规则。

②怎么做部分:

​ 成员的定义是派生类的责任。接口提供了派生类应遵循的标准结构。也就是说接口规定了这个规则,那么继承它的派生类(类/结构)就要按照接口制定的规则办事。

​ (2)接口使用interface关键字声明,并且接口的成员由属性、方法、事件、索引器。

​ (3)按照惯例,接口的名称必须以大写的 I 开头

2、接口的作用

​ 在c#中,接口时独立于类来定义的。接口可以理解为一种约束,使得实现这个接口的类或者结构可以在形式上保持一致。也就是说接口可以看作为基类让类来继承约束类,并且还可以多继承,但是接口不能作为派生类继承其他的类。

3、接口如何声明

(1)接口的声明格式

	/// <summary>
    /// 定义一个工作的接口
    /// </summary>
    interface IWork
    {
         void Working();//接口成员不能有方法体
    }

(2)接口的继承

	/// <summary>
    /// 定义一个工作的接口
    /// </summary>
    interface IWork
    {
        void Working();//接口成员没有实例方法,也就是没有方法体,需要派生类重写接口中的所有方法
    }
    /// <summary>
    /// 定义一个人类,来继承接口
    /// </summary>
    public class Person : IWork
    {
        public void Working()//并实现接口的方法,也就是重写方法
        {
            Console.WriteLine("我是继承接口后的Person类");
        }
    }
//外部调用
 class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person();//实例化Person对象
            p.Working();//调用person继承接口后拥有的重写方法working
            Console.ReadKey();
        }
    }

4、接口的特征

​ (1)接口类似于被abstract关键字修饰的抽象基类,不能直接使用new关键字来实例化接口
在这里插入图片描述
​ (2)接口不能定义字段。接口中的方法都是抽象的或者说属性、方法、事件都没有实现部分,继承接口的任何非抽象类都必须实现(重写)接口的所有成员
在这里插入图片描述
​ (3)接口自身可以继承多个接口,类和结构也可以继承多个接口,但是接口不能继承类

  	/// <summary>
    /// 定义一个工作的接口
    /// </summary>
     interface IWork
    {
       string Eat { get; set; }
        void Working();
    }
    /// <summary>
    /// 定义一个跑的接口
    /// </summary>
    interface IRun:IWork
    {
        void Run();
        //因为接口之间可以相互继承,所以,IRun接口就继承了IWork接口中的成员方法IWorking
        //此时当类或结构继承IRun接口时,不仅要重写IRun的接口,还要重写IWork的接口
    }
    /// <summary>
    /// 定义一个人类,来继承接口
    /// </summary>
    public class Person : IRun
    {
        public string Eat { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

        public void Working()//并实现IWork接口的方法,也就是重写方法
        {
            Console.WriteLine("我是继承接口IRun后的Person方法Working");
        }
        public void Run()//重写IRun接口的方法
        {
            Console.WriteLine("我是继承接口IRun后的Person方法Run");
        }
    }

​ (4)接口不能包含静态成员、常量、字段、运算符,实例构造函数、析构函数或类型
在这里插入图片描述
​ (5)接口声明时可以使用public、internal(接口默认的)修饰符,但是接口成员都是自动公开的,不能使用任何访问修饰符,包括public

​ (6)当一个类既继承了基类,又继承接口的时候,必须基类写在前面,基类和接口用逗号隔开

​ **注意:**一个类只能有一个基类,但可以继承许多接口

例子:

	/// <summary>
    /// 接口:IWork
    /// </summary>
    public interface IWork
    {
        void Working();
    }
    /// <summary>
    /// 接口:IRun
    /// </summary>
    public interface IRun
    {
        void Runt();
    }
    /// <summary>
    /// 基类:人类
    /// </summary>
    public class Person
    {
        public void Sing()
        {
            Console.WriteLine("我会唱歌");
        }
    }	
 /// <summary>
    /// 派生类:学生类
    /// </summary>
    class Student:Person,IWork,IRun//Student类继承Person(基类)、接口IWork、接口IRun
    {
        /// <summary>
        /// 隐式接口:重写IWork接口中的Working方法
        /// </summary>
        public void Working()
        {
            Console.WriteLine("我是派生类Student,我继承并重写了接口IWork,我会工作");
        }
        /// <summary>
        /// 隐式接口:重写IRu接口中的Runt方法
        /// </summary>
        public void Runt()
        {
            Console.WriteLine("我是派生类Student,我继承并重写了接口IRun,我会跑步");
        }
    }
//外部调用
 class Program
    {
        static void Main(string[] args)
        {
            Student s = new Student();//实例化学生Student对象
            s.Working();//这个是重写接口IWork中Working的方法
            s.Runt();//这个是重写接口IRun中Runt的方法
            s.Sing();//这个是继承Person类的方法
            Console.ReadKey();
        }
    }

输出结果:
在这里插入图片描述

5、接口的分类

(1)显示实现接口

​ 实现接口的过程中,若有两个接口中的某些成员有相同的名字则需用显示实现来解决,显示实现接口的类不能直接调用继承接口的成员。显示实现接口只能通过对应的接口访问对应接口中的方法,用实现类去访问时访问不到。其实很好理解,就是显示实现需要指定到具体的哪个接口的哪个方法,防止函数名冲突,调用模糊。

显式实现接口的特点:

​ 1、显式实现的接口不能有访问修饰符

​ 2、显式实现接口的方法可以看到方法的归属地([—某接口—].< 方法名 >),也就是说能够看到方法是从哪个接口而来的

​ 3、显式实现接口的调用不能通过 类名.方法名 直接调用,必须通过多态,就是接口自己调用自己的方法或者属性,比如: 接口名称 P=new 类名称(); p.方法名();

例如:

	/// <summary>
    /// 接口:IWork
    /// </summary>
    public interface IWork
    {
        void Working();
    }
    /// <summary>
    /// 接口:IRun
    /// </summary>
    public interface IRun
    {
        void Runt();
    }
 /// <summary>
    /// 基类:人类
    /// </summary>
    public class Person
    {
        public void Sing()
        {
            Console.WriteLine("我会唱歌");	
        }
    }


	/// <summary>
    /// 派生类:学生类
    /// </summary>
    class Student:Person,IWork,IRun//Student类继承Person(基类)、接口IWork、接口IRun
    {
        /// <summary>
        /// 显式实现接口:重写IWork接口中的Working方法
        /// </summary>
         void IWork.Working()
             //注意:显式实现接口没有访问修饰符,并且函数名是(对应接口.接口方法名)
        {
            Console.WriteLine("我是派生类Student,我继承并重写了接口IWork,我会工作");
        }
        /// <summary>
        /// 显式实现接口:重写IRu接口中的Runt方法
        /// </summary>
        void IRun.Runt()
             //注意:显式实现接口没有访问修饰符,并且函数名是(对应接口.接口方法名)
        {
            Console.WriteLine("我是派生类Student,我继承并重写了接口IRun,我会跑步");
        }
    }
 //外部调用
 class Program
    {
        static void Main(string[] args)
        {
            IWork s = new Student();//多态,接口IWork指向了对象Student
            IRun r = new Student();//多态,接口Irun指向了对象Student
            Student s1 = new Student();//这个是实例化Student类
            //用对应接口调用对应的方法
            s.Working();//接口s就是IWork调用它的方法Working
            r.Runt();//接口R就是IRun调用它的方法Runt
            s1.Sing();//通过派生类调用基类的方法
            Console.ReadKey();
        }
    }

输出结果:

在这里插入图片描述

(2)隐式实现接口

​ 隐式实现接口,当派生类继承一个接口的情况下就用隐式显示。这样就可以直接通过类名直接调用接口中的方法。

隐式实现接口的特点:

​ 1、隐式实现的接口必须有访问修饰符public

​ 2、隐式实现的接口不能看到方法的归属地,就是说不能看到方法来自哪个接口

​ 3、隐式实现的接口可以直接通过 类名.方法名 来直接调用

例子:

    /// <summary>
    /// 接口:IWork
    /// </summary>
    public interface IWork
    {
        void Working();
    }
	/// <summary>
    /// 接口:IRun
    /// </summary>
    public interface IRun
    {
        void Runt();
    }
    /// <summary>
    /// 基类:人类
    /// </summary>
    public class Person
    {
        public void Sing()
        {
            Console.WriteLine("我会唱歌");
        }
    }
	/// <summary>
    /// 派生类:学生类
    /// </summary>
    class Student:Person,IWork,IRun//Student类继承Person(基类)、接口IWork、接口IRun
    {
        /// <summary>
        /// 隐式实现接口:重写IWork接口中的Working方法
        /// </summary>
        public void Working()
        {
            Console.WriteLine("我是派生类Student,我继承并重写了接口IWork,我会工作");
        }
        /// <summary>
        /// 隐式实现接口:重写IRu接口中的Runt方法
        /// </summary>
        public void Runt()
        {
            Console.WriteLine("我是派生类Student,我继承并重写了接口IRun,我会跑步");
        }
    }
//1、外部调用可以使用显示实现调用的方法(多态)
//2、同时隐式显示也可以使用类直接调用,这里介绍第二种
  class Program
    {
        static void Main(string[] args)
        {
            Student s1 = new Student();//直接使用常见的类调用就可以
            s1.Working();
            s1.Runt();
            s1.Sing();
            Console.ReadKey();
        }
    }

输出结果:

在这里插入图片描述

6、总结

(1)当类实现一个接口时,通常使用隐式接口实现,这样可以方便的访问接口方法和类自身具有的方法和属性

(2)当类实现多个接口时,并且接口中包含相同的方法签名,此时使用显式接口实现。即使没有相同的方法签名,仍推荐使用显式接口,因为可以标识出哪个方法属于哪个接口

(3)隐式接口实现,类和接口都可以访问接口中的方法;显式接口实现,只能通过接口访问

(4)隐式接口实现由默认的访问修饰符public,而显式接口实现不能有访问修饰符,但可以看到方法的来源


以上均为个人在学习c#接口时对一些重要知识的总结,希望可以帮到跟我一样的小白。当然,如果本篇文章有什么不足之处,或者造成了一些误导,还希望各位朋友能够指点迷津,谢谢!

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

御弟謌謌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值