zoukankan      html  css  js  c++  java
  • C#中的接口实现多态

    我们都知道虚方法实现多态,抽象方法实现多态等,我们今天来看看如何使用接口实现多态

    1.首先我们先要来了解了解什么是接口,它存在的意识

        01.接口就是为了约束方法的格式(参数和返回值类型)而存在的

        02.接口可以实现多继承,弥补单继承的缺陷。

      03.接口可以看成是一个特殊的抽象类,通过反编译看源码可知

        04.接口中方法不用访问修饰符,因为CLR会自动添加,并且不能有方法体

        05.如果一个类实现了某个接口,就得实现该接口中所有的方法

        06.接口要谨慎使用,防止出现接口污染!

        07.接口仅仅代表一种能力,实现该接口的类和接口没有继承关系

        08.接口是用来实现的,类是用来继承的。

        09.其实很多时候,看似可以不用接口,因为接口就是一个方法的约定,

        表明你这个类必须要有某些方法,但是不写接口也可以有这些方法,用了接口,

        就可以使用接口变量,统一调用,实现多态

       10.接口中只能定义方法,不能定义变量。

    2.抽象类和接口的区别:

    当需要的各个对象之间存在父子类关系时,可以考虑使用抽象类,

    当各个对象之间不存在继承关系,只是有相同的能力时,而已考虑使用接口

    3.接口的通俗理解

       01.飞机会飞,鸟会飞,他们都继承了同一个接口“飞”;但是F22属于飞机抽象类,

       鸽子属于鸟抽象类。

       02.就像铁门木门都是门(抽象类),你想要个门我给不了(不能实例化),

       但我可以给你个具体的铁门或木门(多态);而且只能是门,你不能说它是窗(单继承);

       一个门可以有锁(接口)也可以有门铃(多实现)。

       门(抽象类)定义了你是什么,接口(锁)规定了你能做什么

       (一个接口最好只能做一件事,你不能要求锁也能发出声音吧(接口污染))

       

    下面我们举个用接口实现多态的例子:

    01.新建一个飞的接口

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 接口
    {
        //飞的接口
       public interface IFly
       {
           //接口中方法不用访问修饰符,因为CLR会自动添加,并且不能有方法体
           void Say();
    
       }
    }

    02.创建一个吃的接口

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 接口
    {
        //吃的接口
       public interface IEat
       {
           //接口中方法不用访问修饰符,因为CLR会自动添加,并且不能有方法体
           void eat();
       }
    }

    03.创建一个鸟类来实现飞的接口和吃的接口

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 接口
    {
        //鸟实现飞的接口和吃的接口 
        public class Grid:IFly,IEat   //注意  接口:接口叫继承  ,类:接口叫实现
        {
    
            //如果一个类实现了某个接口,就得实现该接口中所有的方法
            public void Say()
            {
                Console.WriteLine("鸟在飞");
            }
    
            public void eat()
            {
                Console.WriteLine("鸟在吃");
            }
        }
    }

    04.创建一个飞机类实现飞的接口

    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 接口
    {
        //飞机实现飞的接口
       public class Plan:IFly
        {
    
            public void Say()
            {
                Console.WriteLine("飞机在飞");
            }
        }
    }

    05.在Main方法实现调用

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 接口
    {
        class Program
        {
            static void Main(string[] args)
            {
                //定义飞接口数组实例化对象
                IFly[] iFlies =
                {
                    new Grid(), 
                    new Plan()
                };
                //循环数组调用方法实现多态
                foreach (IFly iFly in iFlies)
                {
                    iFly.Say();
                }
                //鸟吃实例化对象
                IEat iEats = new Grid();
                //调用方法实现多态
                iEats.eat();
                
                Console.ReadLine();
            }
        }
    }

    这样就可实现多态了,运行结果如下:

    注:如果有一个类要实现两个接口,不巧的是这两个接口(如:IFly,IPlay)中右两个同命名的方法(Eat)

    我们都知道

    如果一个类实现了某个接口,就得实现该接口中所有的方法

    这怎么办呐?自有解决的方法的:

      我们就可以使用接口名.方法来实现

      //实现了IFly和IPlay两个接口,但两个接口中都有Eat方法
       public class Dog:IFly,IPlay
        {
            //如果一个类实现了某个接口,就得实现该接口中所有的方法
           //这样我们就可以使用接口名.方法来实现
            void IFly.Eat()
            {
                
            }
    
            void IPlay.Eat()
            {
                
            }
        }

     4.接口总结(摘录):

         接口是组件之间的协议,描述了组件对外提供的服务。从技术上讲接口是一组包含了函数型方法的数据结构。 通过这组数据结构,客户代码可以调用组件对象的功能。接口可以从父接口中继承。接口的继承首先是说明性继承,不是实现性继承,它的实现需要通过类或结构来实现;其次接口继承可以是多继承。

     属性的本质是方法,索引器的本质是属性。

          接口包含的成员有方法、属性、索引指示器和事件。由于接口允许多继承,在可能发生二义性的地方可以采用全权名来避免。可以用类来实现接口。在类中定位接口成员的实现称之为接口映射。类必须为接口的所有成员提供具体的实现,包括接口中显式定义的成员, 以及接口从父接口中继承而来的成员。同样,在对接口的实现过程中可以采用显式接口成员执行体来避免产生二义性。派生类可以对基类已经实现的接口进行重实现。

           抽象类也可以实现接口,但接口成员必须映射到抽象类的抽象成员。抽象类的派生类如果是非抽象类,则必须通过方法重载来实现接口成员。

  • 相关阅读:
    nginx显示中文乱码
    Job for mariadb.service failed because the control process exited with error code. See "systemctl status mariadb.service" and "journalctl -xe" for details
    linux 7 网卡配置
    zabbix 离线安装
    linux alias 设置命令别名
    重启redis shell脚本
    docker离线安装
    ansible 批量添加用户
    linux 7 离线安装ansible
    Linux 7 配置163yum源
  • 原文地址:https://www.cnblogs.com/zhangzongle/p/5385068.html
Copyright © 2011-2022 走看看