C#编程利器之三:接口(Interface)

C#接口是一个让很多初学者容易迷糊的东西,用起来好象很简单,定义接口,然后在里面定义方法,通过继承与他的子类来完成具体的实现。但没有真正认识接口的作用的时候就觉得用接口是多此一举,当然你这样想是绝对错误的。在软件设计中有一个非常重要的原则就是:面向接口编程,依赖与接口或抽象层。可见接口在真正的开发中是多么的重要。

在之前C#编程利器之一:类(Class)一文里介绍了类的相关知识,本文主要介绍OO编程中的另一个重要知识点--接口。在某种程度上说,接口也是类,一种特殊的类或抽象类。 更准确说接口只包含方法委托事件的签名。方法的实现是在实现接口的类中完成的[MSDN]。

一、接口的定义

如上MSDN上对接口的定义,接口只包含方法、委托或事件的签名。这句话用更通俗点的解释便是,接口只是负责完成定义的操作,而不去实现具体的细节。如下面的IPlayer接口,它是一个玩游戏的接口,里面只是定义了相应的方法,而不带方法的具体实现,代码如下:

 1/**//// <summary>
 2/// 玩游戏接口
 3/// </summary>
 4public interface IPlayer
 5{
 6    /**//// <summary>
 7    /// 获取玩家的名字
 8    /// </summary>
 9    /// <returns>玩家的名字</returns>
    string GetName();

    /**//// <summary>
    /// 由Player决定出什么手势
    /// </summary>
    /// <returns>本接口定义的三个常量之一</returns>
    string Show();
}

以上就是一个典型的接口的定义。定义了一个名为IPlayer的接口,内部定义了两个方法GetName和Show。除了在接口里定义方法以外,我们还可以定义属性、索引及事件等,详细请查看MSDN上的定义或是相关书籍,这里以属性为例简单介绍下,在接口里只能定义不实现,具体的实现是交给其子类去完成的,那么属性应该怎么定义呢?

通常我们定义属性如下:

/**//// <summary>
/// 定义_Name属性,并提供get;set属性访问器
/// </summary>
private string _Name;
public string Name
{
    get { return _Name; }
    set { _Name = value; }
}

那么在接口中又是怎么定义属性,并让其子类去实现呢?如下代码段:

 1/**//// <summary>
 2/// 定义接口,并在接口里定义一名为Name的属性
 3/// </summary>
 4public interface IAttribute
 5{
 6    string Name { get;set;}
 7}
 8/**//// <summary>
 9/// 定义一个类去继承IAttribute接口,并实现其属性
/// </summary>
public class Component : IAttribute
{
    public string Name
    {
        get
        {
            return "张三";
        }
        set
        {
            this.Name = value;
        }
    }
}

二、接口的实现

在本文开始部分曾经说过,接口只负责定义,不负责实现,具体的实现是交给他的子类去完成的。 OK,现在我们就以上面定义的玩游戏的接口IPlayer为例,来简单的介绍下接口的实现。

就拿我的趣味编程中的玩剪刀石头布的案例来说吧,爷爷和奶奶从小就教授小孙子各中东西,其中玩趣味游戏就他们常有的事,可小孙子还小不知道变换,每次都出剪刀,这样能赢他爷爷吗?有了这个分析,我们可以怎么做呢?上面定义了接口,我们是不是直接去实现这个接口便OK了。爷爷和小孙子玩游戏,那么就定义两个类去继承IPlayer接口。代码如下:

/**//// <summary>
/// 出手动作状态
/// </summary>
public class Options
{
    public static readonly string JIANDAO = "剪刀";
    public static readonly string SHITOU = "石头";
    public static readonly string BU = "布";
}

游戏里只会出现这三种动作状态,所以我们可以进行封装,这里是通过类封装的,当然我们也可以通过别的相关技术来封装,比如在本系列第二篇文章《C#编程利器之二:结构与枚举(Structure and enumeration)》 里介绍的结构与枚举,本例中所出现的这三中不变的状态完全可以使用结构或枚举来封装,详细请阅读上篇文章。下面是定义爷爷(Grandpa)类和孙子(Grandson)类去实现接口(IPlayer)了。代码如下:

 1/**//// <summary>
 2/// 爷爷--玩家之一
 3/// </summary>
 4public class Grandpa:IPlayer
 5{
 6    public string GetName()
 7    {
 8        return "爷爷";
 9    }

    public string Show()
    {
        Random random = new Random();
;
        switch (i)
        {
: return Options.JIANDAO;
: return Options.SHITOU;
            default: return Options.BU;
        }
    }
}
 1/**//// <summary>
 2/// 孙子--玩家之一
 3/// </summary>
 4public class Grandson:IPlayer
 5{
 6    public string GetName()
 7    {
 8        return "孙子";
 9    }

    public string Show()
    {
        return Options.JIANDAO;
    }
}

如上,我们的GrandPa和GrandSon就实现了接口IPlayer,如下图示:

三、接口的继承

关于这点这里就不作详细的介绍,只需要记住有这样一句话就万岁了:“一个接口可从一个或多个基接口继承”。示意性代码:

interface IA { }
interface IB:IA { }
interface IC : IA, IB { }
interface ID : IA, IB, IC { }

四、接口的特性

接口除了可以包含方法之外,还可以包含属性、索引器、事件等,而且这些成员都被定义为公有的。除此之外,不能包含任何其他的成员,例如:常量、域、构造函数、析构函数、静态成员。一个类可以直接继承多个接口,但只能直接继承一个类(包括抽象类)。

从类型上来说接口是引用类型的,类似于类,和抽象类的相似之处有三点:

1、不能实例化;
      2、包含未实现的方法声明;
      3、派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他成员);

五、接口与回调

通常情况下,我们创建一个对象,并马上直接去使用它的方法。然而,在有些情况下,希望能在某个场景出现后或条件满足时才调用此对象的方法。回调就可以解决这个“延迟调用对象方法”的问题。这个被调用方法的对象称为回调对象。

首先创建一个回调对象,然后再创建一个控制器对象,将回调对象需要被调用的方法告诉控制器对象.控制器对象负责检查某个场景是否出现或某个条件是否满足.当此场景出现或此条件满足时,自动调用回调对象的方法.示意性代码如下:

 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4
 5namespace CallBack
 6{
 7    class Program
 8    {
 9        static void Main(string[] args)
        {
            //创建一个控制器对象,将提供给它的回调对象传入 
            Resolve resolve = new Resolve(new PlayBasketball());
            resolve.Play();

            resolve = new Resolve(new PlayFootball());
            resolve.Play();
        }
    }

    /**//// <summary>
    /// 定义一个接口--回调对象
    /// </summary>
    public interface IPlayer
    {
        void Play();
    }

    /**//// <summary>
    /// 篮球 
    /// </summary>
    public class PlayBasketball:IPlayer
    {
        public void Play()
        {
            Console.WriteLine("玩篮球");
        }
    }

    /**//// <summary>
    /// 足球
    /// </summary>
    public class PlayFootball : IPlayer
    {
        public void Play()
        {
            Console.WriteLine("玩足球");
        }
    }

    /**//// <summary>
    /// 控制角色--控制器对象
    /// </summary>
    public class Resolve 
    {
        //持有一个接口的引用,通过构造方法初始化
        private IPlayer player;
        public Resolve(IPlayer player)
        {
            this.player = player;
        }

        public void Play()
        {
            player.Play();
        }
    }
}

关于接口的相关知识点本文就介绍于此,更详细的学习接口这门功夫请大家查阅相关资料。

注: 文章转载自: http://beniao.cnblogs.com/http://www.cnblogs.com/   作者 : Beniao

C#编程利器之三:接口(Interface)【转】的更多相关文章

  1. java中的接口interface

    关于接口 接口描述了实现了它的类拥有什么功能.因为Java是强类型的,所以有些操作必须用接口去约束和标记.接口作为类的能力的证明,它表明了实现了接口的类能做什么. 类似与class,interface ...

  2. [.net 面向对象编程基础] (16) 接口

    [.net 面向对象编程基础] (16) 接口 关于“接口”一词,跟我们平常看到的电脑的硬件“接口”意义上是差不多的.拿一台电脑来说,我们从外面,可以看到他的USB接口,COM接口等,那么这些接口的目 ...

  3. C#编程利器之一:类(Class)【转】

    C#编程利器之一:类(Class) 面向对象的程序设计(Object-Oriented Programming,简记为OOP)是一种功能非常强大的编程方法,立意于创建软件重用代码,以类为基础去思考编程 ...

  4. VS2010/MFC编程入门之三十六(工具栏:工具栏资源及CToolBar类)

    上一节中鸡啄米讲了菜单及CMenu类的使用,这一节讲与菜单有密切联系的工具栏. 工具栏简介 工具栏一般位于主框架窗口的上部,菜单栏的下方,由一些带图片的按钮组成.当用户用鼠标单击工具栏上某个按钮时,程 ...

  5. TCP/IP网络编程系列之三(初级)

    TCP/IP网络编程系列之三-地址族与数据序列 分配给套接字的IP地址和端口 IP是Internet Protocol (网络协议)的简写,是为首发网络数据而分配给计算机的值.端口号并非赋予计算机值, ...

  6. python面向对象编程 继承 组合 接口和抽象类

    1.类是用来描述某一类的事物,类的对象就是这一类事物中的一个个体.是事物就要有属性,属性分为 1:数据属性:就是变量 2:函数属性:就是函数,在面向对象里通常称为方法 注意:类和对象均用点来访问自己的 ...

  7. Py修行路 python基础 (十五)面向对象编程 继承 组合 接口和抽象类

    一.前提回忆: 1.类是用来描述某一类的事物,类的对象就是这一类事物中的一个个体.是事物就要有属性,属性分为 1:数据属性:就是变量 2:函数属性:就是函数,在面向对象里通常称为方法 注意:类和对象均 ...

  8. delphi 接口Interface

    学习 delphi 接口 一切都是纸老虎!!! 第四章          接口 前不久,有位搞软件的朋友给我出了个谜语.谜面是“相亲”,让我猜一软件术语.我大约想了一分钟,猜 出谜底是“面向对象”.我 ...

  9. Python编程-继承和接口

    一.继承 1.什么是继承 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类. 继承的好处: 可以使用现有类的所有功能,并在无 ...

随机推荐

  1. 定期来一次“绩效谈话”(摘自易中)

    值得借鉴学习 管理者和下属直接的互动关系当中,需要有一个定期的反馈机制.员工在工作当中需要管理者给他持续地反馈.以下是一个绩效谈话的标准程序: 一:说明会谈的目的和时间:我们用10分钟对你上一阶段的工 ...

  2. jS事件:target与currentTarget区别

    target在事件流的目标阶段:currentTarget在事件流的捕获,目标及冒泡阶段.只有当事件流处在目标阶段的时候,两个的指向才是一样的, 而当处于捕获和冒泡阶段的时候,target指向被单击的 ...

  3. 手机web站点和手机app 技术选型的困惑于思考

    今年一直在关注移动端技术的发展,自己也用博客园的rss接口玩了半年,关于技术选型的困惑和大家说说 一 趋势 随着手机硬件不断的升级,外加4g牌照的发放,不出2年时间移动端web站点和手机app一定会进 ...

  4. URAL 1117. Hierarchy(DP)

    题目链接 这破题,根本看不懂题意啊...题意:一棵中序遍历是1 2 3 4 5...的满二叉树,从a a+1 a+2 a+3 b,总共多少步.x到y的距离为中间有多少个点.a > b没注意2Y. ...

  5. mysql的小总结

    1.什么是数据库 ? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,它产生于距今六十多年前,随着信息技术和市场的发展,特别是二十世纪九十年代以后,数据管理不再仅仅是存储和管理数 ...

  6. jsonkit mrc于arc混编

  7. ios面试(2015.10.30)

    今天去深圳市丰泰瑞达实业有限公司面试,面试分为笔试和面试两部分,结果非常不理想,不过学到很多.面试题记录如下: 1.tableview的三个常用方法的实现 - (NSInteger)numberOfS ...

  8. JavaScript事件对象【转】

    一. 事件对象 事件处理三部分组成:对象.事件处理函数=函数.例如:单击文档任意处. 1.鼠标按钮 非 IE(W3C)中的 button 属性 0 表示主鼠标按钮(常规一般是鼠标左键) 1 表示中间的 ...

  9. 学习bootstrap心得

    Bootstrap 使用了一些 HTML5 元素和 CSS 属性.为了让这些正常工作,您需要使用 HTML5 文档类型(Doctype). 因此,请在使用 Bootstrap 项目的开头包含下面的代码 ...

  10. [LintCode] Minimum Size Subarray Sum 最小子数组和的大小

    Given an array of n positive integers and a positive integer s, find the minimal length of a subarra ...