接口

C#中的接口与Java类似,略有不同。

1、接口的定义

  C#中接口可以包含一个或多个成员,这些成员可以是方法、属性、索引指示器和事件,但不能是常量、域操作符、构造函数或析构函数,而且不能包含任何静态成员。

  接口成员默认访问方式是public,接口成员声明不能包含任何修饰符,比如成员声明前不能加abstract, public, protected, internal, private, virtual, override 或static 修饰符。

  给一个接口的定义实例:

复制代码

复制代码
interface IExample

{ 
//注意: 与Java不同的是,C#中接口声明不能添加任何修饰符,默认是public 

//定义方法 
void F(int value);
//定义属性 
string P { get; set; }
//定义索引指示器 
string this[int index] { get; set; } 
//定义事件 
event EventHandler E; 
}
View Code
复制代码

2、对接口成员的访问

由于接口是支持多继承的,在多继承中,如果两个父接口都包含了同名的成员,这就会产生二义性,这时需要进行显式的声明。

如下面的实例:

复制代码
interface IBookName
    {
        void cwName(string name);
        string WriteName { get; set; }
    }

interface ITeacherName
    {
        void cwName(string name);
        string WriteName { get; set; }
    }

interface IDetail:IBookName,ITeacherName
    {
    }

public class PersonInfo : IDetail
    {
        private string writename;
        void IBookName.cwName(string name)
        {
            Console.WriteLine("请输入书名:"+name+"......."+writename); 
        }

         string IBookName.WriteName
        {
            get
            {
                return writename;
            }
            set
            {
                writename =value;
            }
        }

        void ITeacherName.cwName(string name)
        {
            Console.WriteLine("请输入教师名:" + name + "......." + writename); 
        }

        string ITeacherName.WriteName
        {
            get
            {
                return writename;
            }
            set
            {
                writename = value;
            }
        }
    }


static void Main(string[] args)
        {
            PersonInfo personInfo = new PersonInfo();
            Console.WriteLine("请输入书名:");
            ((IBookName)personInfo).WriteName = Console.ReadLine();
            ((IBookName)personInfo).cwName("");
            Console.WriteLine("请输入老师名:");
            ((ITeacherName)personInfo).WriteName = Console.ReadLine();
            ((ITeacherName)personInfo).cwName("老师");
            Console.ReadKey();
        }
View Code
复制代码

3、接口的多继承也带来了一定的问题,这里主要是使用new覆盖的问题,例如下面的示例:

复制代码
interface IBase
    {
        void cwName(string name);
        string WriteName { get; set; }
    }

interface ITeacherName:IBase
    {
        new void cwName();
    }

interface IBookName:IBase
    {
        void Gcwname();
        void cwName(string name);
    }

 interface IDetail:IBookName,ITeacherName
    {
    }

public class PersonInfo : IDetail
    {
        void IBookName.Gcwname(){}
        void IBase.cwName(string name){}
        void ITeacherName.cwName(){}
        void IBookName.cwName(string name) {}
    }

//从这里可以看出 new了基层接口时,就会多出来一个接口实现,如果一个接口继承了基层接口,同时又有相同的方法名,那么原理就同上    
View Code
复制代码

4、 接口的重实现(也就是重映射)

类必须为在声明中列出的所有接口成员提供具体的实现。在类中定位接口成员的实现称之为接口映射(interface mapping)。

  相关示例如下:

复制代码

复制代码
interface IControl
{
    void Paint();
}
class Control: IControl
{
    public void Paint() 
    {
        //do somethings
    }
}
class TextBox: Control
{
    new public void Paint() 
    {
        //do somethings
    }
}

/*
 * TextBox 中的Paint 方法覆盖了Control 中的Paint 方法,但却没有改变Control.Paint 对 IControl.Paint 的映射
 * 在类的实例和接口的实例中对Paint方法的调用会产生下面这样的结果:
 * Control c = new Control();
 * TextBox t = new TextBox();
 * IControl ic = c;
 * IControl it = t;
 * c.Paint(); // invokes Control.Paint();
 * t.Paint(); // invokes TextBox.Paint();
 * ic.Paint(); // invokes Control.Paint();
 * it.Paint(); // invokes Control.Paint();
 * 如果需要让it去调用TextBox.Paint(),就要用virtual方法去实现Control中的Paint,然后再TextBox中new一个Paint()
 */
View Code
复制代码

5、接口的重实现(也就是重映射)

  所谓接口的重实现,其实就是接口的重映射。示例如下:

复制代码
复制代码

interface IControl
{
    void Paint();
}
class Control: IControl
{
    void IControl.Paint() 
    {
        //do somethings
    }
}
class MyControl: Control, IControl
{
    public void Paint() {}
}

/*
 * Control 把IControl.Paint 映射到了Control.IControl.Paint 上, 
 * 但这并不影响在MyControl 中的重实现(重映射)
 * 在MyControl 中的重实现中,IControl.Paint 被映射到MyControl.Paint 之上
 */
View Code
复制代码

6、抽象类与接口

  其实接口就是一种纯的抽象类,与接口不同的是:抽象类可以继承接口,把接口映射到抽象函数。示例如下:

复制代码
interface IMethods
{
    void F();
    void G();
}
abstract class C : IMethods
{
    //这里将IMethods的F()和G()映射到了类C的抽象方法上
    public abstract void F();
    public abstract void G();
}
View Code
复制代码

 7、接口作为类型返回,同时作为一个参数

复制代码
public  interface IShape
    {
        int Area { get; set; }
        void Caculate();
    }


public  class Circle:IShape
    {
      int area = 0;
      public Circle(int m_Area)
      {
          area = m_Area;
      }

      public int Area
      {
          get
          {
              return area;
          }
          set
          {
              area = value;
          }
      }

      public void Caculate()
      {
          Console.WriteLine("计算面积");
      }
    }

public class MyClass
    {
       public MyClass()
       { }
       public void OMyClass(IShape m_shape)
       {
           m_shape.Caculate();
           Console.WriteLine(m_shape.Area);
       }
    }


public class MyOutput
    {
       public IShape OMyOutput(IShape m_shape)
       {
           m_shape.Area = 100;
           return m_shape;
       }
    }

static void Main(string[] args)
        {
            Circle circle = new Circle(35);
            MyClass myClass = new MyClass();
            myClass.OMyClass(circle);
            MyOutput myOutput = new MyOutput();

            Circle circle1 = (Circle)myOutput.OMyOutput(circle);
            Console.WriteLine(circle1.Area);
            Console.ReadLine();
        }
View Code
复制代码

 

原网址:http://www.cnblogs.com/notifier/archive/2010/05/17/1735385.html

posted @   zmztyas  阅读(193)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示