C# 接口浅析

来源:互联网 发布:linux as系统无法启动 编辑:程序博客网 时间:2024/06/09 16:38

        接口的定义:接口就是一组抽象成员的命名集合。

首先,简单的区分一下接口和抽象基类的区别。抽象类的特点,包含一个或多个抽象方法或属性的类必须定义为抽象类;继承抽象类的派生类必须实现抽象类的所有抽象方法或属性,否则该派生类也必是抽象类;抽象类必须是公共的(public)。

1、在C#语言中,一个类可以实现多个接口,但是只能有一个基类(包括抽象类);

2、抽象类可以包含成员的实现,可以定义构造函数、数据字段、非抽象成员(具体实现),但接口只能包含抽象成员。

3、共同的特点就是不能被实例化,都可以被继承。

       网上一个比方十分有趣,飞机会飞,鸟会飞,他们都继承了同一个接口“飞”,但是F22继承飞机抽象类,鸽子继承鸟抽象类。飞机抽象类规定F22只能是飞机,不能是其他的,F22和鸽子他们有个共同的规范就是“飞”。 接口有什么用,比如说,IDbConnection接口定义了一组所有ADO.NET连接对象都共有的成员。因此也就保证了每一个连接对象都支持诸如Open()、Close()、CtreateCommand()等方法,每一个不同的连接对象(MySqlConnection 和SqlConnection)都可以以自己的方式来实现这些方法,它是一种统一的规范,为不相关的类提供通用的处理服务。

第一:接口的定义和实现

       .net基础类库中提供了大量的接口,多以大写字母“I”作为前缀,以“able”作为后缀(能做什么)。

    public interface IEatable    {        //隐式公共的和抽象的        void EatFunc();        /*定义接口需要注意的一些地方         *1、不能有字段         *2、不能有构造函数         *3、接口不能提供方法实现         *4、命名空间中定义的接口无法显式声明为 private、protected 或 protected internal        */    }    public abstract class ThingClass    {        //抽象类可以定义字段        public int numOfWeight;        public abstract int GetWeightFunc();        public static void CommonFunc()        {            Console.WriteLine("抽象类可以有方法的具体实现");        }    }    public class PersonClass : ThingClass,IEatable    {        public void EatFunc()        {            //这里是PersonClass对IEatable接口EatFunc具体实现            Console.WriteLine("This is PersonClass.EatFunc");        }        //必须要实现GetWeightFunc方法,否则PersonClass也为抽象类        public override int GetWeightFunc()        {            Console.WriteLine("人大概有100多斤左右");            return 100;        }            }    public class DogClass : ThingClass, IEatable    {        public void EatFunc()        {            //这里是DogClass对IEatable接口EatFunc具体实现            Console.WriteLine("This is DogClass.EatFunc");                    }        public override int GetWeightFunc()        {            Console.WriteLine("狗大概有50多斤左右");            return 50;        }    }

         这里也可以看出抽象类和接口的一些区别。

第二:对象级别调用接口、接口作为参数和返回值

        对象级别调用接口

    class Program    {        static void Main(string[] args)        {            //定义接口,但是不能实例化            IEatable iMyEatable = null;            PersonClass myPerson = new PersonClass();            iMyEatable = (IEatable)myPerson;            iMyEatable.EatFunc();            Console.ReadKey();        }    }

         这里显得可能有点多此一举了,因为直接myPerson.EatFunc(),不就行了。我们再添加一个类,机器人类,它并没有实现IEatable接口,它只继承了ThingClass抽象类,

    public class RobotClass : ThingClass    {        public override int GetWeightFunc()        {            Console.WriteLine("机器人大概有200多斤左右");            return 200;        }    }

       假设要实现一个功能,我们要打印出实现IEatable接口方法EatFunc的内容,建一个thingClass数组,但是里面RobotClass并没有实现接口。顺带可以看看接口作为参数,在Program类中添加一个静态方法CommonEatFunc(),

        static void CommonEatFunc(IEatable iEatable)        {            Console.WriteLine("此类实现了接口方法");            iEatable.EatFunc();        }

       使用is关键字来检查是否实现一个接口,还可以使用as关键字来得到指向该接口的引用。

        static void Main(string[] args)        {            Console.WriteLine("-------------------");            ThingClass[] things = { new PersonClass(), new DogClass(), new RobotClass() };            foreach (ThingClass temThing in things)            {                if (temThing is IEatable)                {                    CommonEatFunc((IEatable)temThing);                }                else                {                    Console.WriteLine("此类没有实现接口方法");                }            }            Console.WriteLine("-------------------");            RobotClass myRobot = new RobotClass();            IEatable iMyEatable = myRobot as IEatable;            if (iMyEatable != null)            {                iMyEatable.EatFunc();            }             else            {                Console.WriteLine("RobotClass No Eat");            }            Console.ReadKey();        }

           结果:
          接口也可以作为返回值,构建接口数组(数组成员要实现接口方法)。

第三:接口的显式实现和多重继承

         一个类它可以实现多个接口。因此,很有可能接口中包含重命名的成员,所以我们要处理命名冲突。假设我们有一个IEatable2接口,中也有一个EatFunc成员,而PersonClass都需要实现这两个接口。

    public interface IEatable2    {        void EatFunc();    }

         修改PersonClass类代码

    public class PersonClass : ThingClass,IEatable,IEatable2    {        public void EatFunc()        {            //这里是PersonClass实现IEatable接口EatFunc具体实现            Console.WriteLine("This is PersonClass.EatFunc");        }        ......            }

         当然,这段代码可以通过编译,这里两个接口共享同一个方法实现,但是实际中我们要区分开,这时就需要显式实现接口方法。    

    public class PersonClass : ThingClass,IEatable,IEatable2    {        void IEatable.EatFunc()        {            //这里是PersonClass实现IEatable接口EatFunc具体实现            Console.WriteLine("This is IEatable.EatFunc");        }        void IEatable2.EatFunc()        {            //实现IEatable2接口方法            Console.WriteLine("This is IEatable2.EatFunc");        }        ......           }

        这里需要注意的是,显示实现的接口成员是自动私有的,去掉了public,可以想象一下,如果希望从对象级别隐藏“高级成员”,我们也可以显式接口实现,比如说,在DogClass类中改为IEatable.EatFunc(),那么他也就成为私有,继承DogClass类的子类实例和本身实例就必须通过显式转换提取需要的接口。

        还有就是接口可以扩展多个接口,这就容许我们设计非常灵活的抽象。

        总结一下,接口是.NET框架的一个基本方面,在开发Web、GUI、或者数据库访问类库等等,总会用到接口。经常见到的接口,比如IEnumerable,ICloneable,IComparable等等。

0 0