| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3330 人关注过本帖
标题:什么是接口?
只看楼主 加入收藏
wuman803
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2008-5-16
收藏
 问题点数:0 回复次数:8 
什么是接口?
在编程中有"接口"的概念,请问什么是接口,为什么使用要接口,平常的方法不能解决问题,一定要使用接口吗?什么地方需要用到接口,能不能提供一些使用接口的简单实例吗,然后说一说接口能解决什么具体问题?谢谢!
如果哪位能提供"FIF"小组的有关了的VIP FLASH视频下载吗?
搜索更多相关主题的帖子: 接口 
2008-05-16 22:52
hebingbing
Rank: 6Rank: 6
来 自:黄土高坡
等 级:贵宾
威 望:27
帖 子:3417
专家分:371
注 册:2007-10-22
收藏
得分:0 
接口的概念:接口是一组包含了函数型方法的数据结构。通过这组数据结构,客户代码可以调用组件对象的功能。
其实我认为概念是在自己正真用它的时候才能够彻底理解的,光看上面的概念即使是你倒背如流我也认为你不理解接口是什么东西。
其实接口就是一个类,我们可以认为它就是用interface代替了class的一个类,所以他的声明语法都是和类一样的。但是它是一个特殊的类,特殊之处就在它只声明成员,而不具体实现。所以不能创建这个类(接口)的对象。而继承自接口的类必须实现接口的所有方法。
呵呵……
是不是感觉在说抽象类啊?
是的,这看起来有点像抽象类,抽象类也不能实例化,而且要求派生类实现其抽象方法。但是两者是有区别的。
抽象类的功能要比接口多,抽象类可以有子类继承,而且可以包含状态数据和具体方法。
那么到底是用接口还是用类,就个人经验来说:
(只是自己的经验奥,所以大家可以指点和补充……呵呵……)
决定因素:类型与其继承子类之间的关系。
接口:为类定义一种行为,即它“能干什么”,内置的.net ICloneable接口就是这样一个例子。它允许对象创建自身的副本
类:当继承子类是“一种”基类时,就应该用类,
例如:可以创建一个shape类做为基类,创建circle做为shape的子类,而将改变形状大小的功能做为一个接口方法。
除了作用不同外,类和接口还有许多不同。

    [*]接口不能从类继承。而类是可以的……
    [*]接口可以继承多个接口,而类是不可以的,大家都知道c#是不支持多继承的,它不和c++一样,这是因为它不支持多继承,而可以继承自多个接口,所以接口的概念在c#中就要比c++中要觉得重要一些……
    [*]类可以继承多个接口,但是只能继承一个类……
    [*]接口成员必须是方法,成员属性,事件或索引器。
    [*]所有接口成员必须能public访问
    [*]根据命名约定,接口名必须以大写I开头

本来想举个例子,编个小的程序的,呵呵……
可是偷点懒了……
lz可以到网上去找找,应该很多的,我这里就不给你写了,其实写也是复制粘贴的,我实在是自己不想写了……
其实个人觉得在系统的整个设计中,真正的问题不是选择类还是接口,而是然后最佳的结合使用类和接口,c#不允许多重继承,这使得接口的用途更广,倘若把所需的全部功能过呢都加载到一个基类中,或者建立基类的层次体系来实现所需的全部功能,就实在太费劲了。
更好的解决方法是定义一个基类,然后增加相应的接口来扩展其功能,这样,开发人员就可以直接使用类,而无需考虑方法是否为接口实现(即对接口中方法的具体实现)、另外,开发人员也可以只利用接口,而忽略其他类成员。
当然,你必须认识到使用接口的不足之处,首先设计良好的基类可以提升代码重用性,从而减轻继承子类的实现负担,另外,非抽象类可以增加成员,而不影响已有的派生类,而向接口增加成员的话,则实现该类的所有类都会受到影响。
………………
也就这么多吧……
要是有什么不足地方大家补补……
2008-05-17 11:16
hebingbing
Rank: 6Rank: 6
来 自:黄土高坡
等 级:贵宾
威 望:27
帖 子:3417
专家分:371
注 册:2007-10-22
收藏
得分:0 
下面我再举个例子吧……
本来是不想再举例子的,但是觉得讲那么多还不如一个例子来实际……
程序代码:
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    public interface IshapeFunction  //定义一个接口;
    {
        double GetArea();//定义一个没有实现只有声明的方法,
    }
    class circle : IshapeFunction  //circle继承自IshapeFunction接口,他必须实现IshapeFunction接口中的GetArea()方法;
    {
        private double radius;  //定义半径
        public circle(double rad)    //初始化半径
        {
            radius = rad;
        }
        public double GetArea()      //实现接口中的方法
        {
            return (Math.PI * radius * radius);   //求出面积
        }
        public string ShowMe()   //显示自己
        {
            return ("Circle");
        }
    }
    class Rectangle : IshapeFunction  //Rectangle继承自IshapeFunction接口,他必须实现IshapeFunction接口中的GetArea()方法;
    {
        private double width, height;//定义长和宽
        public Rectangle(double myWidth, double myHeight)//初始化长宽
        {
            width = myWidth;
            height = myHeight;
        }
        public double GetArea()  //求出面积
        {
            return (width * height);
        }
        public string ShowMe()   //显示自己
        {
            return ("Rectangle");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            circle myCircle = new circle(4);  //声明一个circle对象
            IshapeFunction myICircle = myCircle;//创建一个变量,它引用了这个circle对象,不过,由于这个变量指定为IshapeFunction类型,所以它只能访问该接口的成员。这就是所谓的“接口类型”,通过用接口类型,可以有效的创建过滤器,从而限制只能对接口成员进行访问。
            Rectangle myRectangle = new Rectangle(4, 8);//声明一个Rectangle对象。
            IshapeFunction[] myShapes ={ myCircle, myRectangle };//使用接口最大的好处之一在于,程序员可以用相同的方式处理不同的类,只要它们实现相同的接口就可以,下面演示这个功能。
            
            
            Console.WriteLine(myShapes[0].GetArea().ToString());
            Console.WriteLine(myShapes[1].GetArea().ToString());

            Console.WriteLine(myCircle.GetArea().ToString());  //打印mycircle的面积
            Console.WriteLine(myRectangle.GetArea().ToString());//打印myrectangle的面积

            Console.WriteLine(myCircle.ShowMe());
            Console.WriteLine(myRectangle.ShowMe());

            Console.WriteLine(myICircle.GetArea().ToString());
            // Console.WriteLine(myICircle.ShowMe());  上面的可以通过,下面提示出错,因为通过接口类型创建了过滤器,限制只能对接口成员进行访问。
            System.Threading.Thread.Sleep(100000);
        }
    }
}
2008-05-17 13:24
hebingbing
Rank: 6Rank: 6
来 自:黄土高坡
等 级:贵宾
威 望:27
帖 子:3417
专家分:371
注 册:2007-10-22
收藏
得分:0 
IshapeFunction[] myShapes ={ myCircle, myRectangle };
Console.WriteLine(myShapes[0].GetArea().ToString());
Console.WriteLine(myShapes[1].GetArea().ToString());
以上代码创建了一个数组,其中可以包含实现了IShapeFunction接口的任何类,这个数组只关心使用GetArea方法,而不理解(也不需要了解)其他类成员,可以很容易的扩展以上例子,来创建一个处理这个数组的类(无需了解Circle和Rectangle类)
程序代码:
    public class ShapeUtil
    {
        public static double SumAreas(IshapeFunction[] funArray)
        {
            double tot = 0.0;
            for (int i = 0; i < funArray.Length; i++)
            {
                tot += funArray[i].GetArea();
            }
            return tot;
        }
    }
2008-05-17 13:34
hebingbing
Rank: 6Rank: 6
来 自:黄土高坡
等 级:贵宾
威 望:27
帖 子:3417
专家分:371
注 册:2007-10-22
收藏
得分:0 
既然都讲了这么多了,那就顺便再延伸延伸……
编译时不一定知道类是否实现了一个指定的接口,处理包含有很多种类型的集合时往往如此,为了在运行是完成这种检查,可以在代码中使用as和is关键字。
 
程序代码:
circle myCircle = new circle(4);  //声明一个circle对象
IshapeFunction myICircle;
myICircle = myCircle as IshapeFunction;
if (myICircle != null)
{ }
circle myCircle2 = new circle(5.0);

 if (myCircle2 is IshapeFunction)

 { }

由于类可以从基类或和多个接口继承方法,所以所继承的方法就有可能存在同名的情况,为了避免这个二异性,可以在派生类中用接口和方法名来指定接口方法声明
  public double IshapeFunction.GetArea()
{
……
} 

这不仅允许一个类实现多个方法,而且还有另外一个作用,即可以限制只有接口引用才能访问呢这个方法
2008-05-17 13:47
DemoHunter
Rank: 1
来 自:江苏南京
等 级:新手上路
帖 子:7
专家分:0
注 册:2008-5-14
收藏
得分:0 
顶下,努力学啊///

不要问,前进...
2008-05-17 14:56
yms123
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:209
帖 子:12488
专家分:19042
注 册:2004-7-17
收藏
得分:0 
楼主如果学习过一些高级的面向对象设计模式,就知道接口其实作用是很关键的。
2008-05-17 15:24
hebingbing
Rank: 6Rank: 6
来 自:黄土高坡
等 级:贵宾
威 望:27
帖 子:3417
专家分:371
注 册:2007-10-22
收藏
得分:0 
什么叫范型
今天借着wuman803兄弟的窗口再发表一些东西,希望对大家有所帮助……
要理解和掌握范型(generics)的概念,请考虑这样一个需求:创建一个类型来管理一个对象集合。对象可能是不同的类型,其类型在编译时由传递给类的参数指定,此外,集合类必须是类型安全的,这说明这个类只能接受知道类型的对象。
在.net1.0中,创建这样的类是没有办法的,最好的选择莫过于创建一个包含数组(或者其他容器类型)的类,这个数组将所有元素都视为对象,然后需要强制类型转换或使用as操作符来访问实际的对象类,如下面的代码所示,另外还需要包含验证代码,检查数组中存放的对象确实是正确的类型。
程序代码:
 object[] myStack = new object[50];
            myStack[0] = new circle(5.0); //将circle对象保存到数组
            myStack[1] = "Circle";  //将string对象放到数组中
            circle c1 = myStack[0] as circle;
            if (c1 != null)
            {
                circle c2 = (circle)myStack[1];
            }

.net2.0引入了范型,他提供了一个很棒的解决方案,可以取消强制类型转换,显式的类型检查,以及值类型对象的装箱等工作,使用范型的主要难点在于,要熟悉范型(可能针对类、接口、和接口)的语法。
要熟悉语法,最好的做法是将范型视为这样一种方法,它能把你要处理的数据类型做为参数传递给范型类型
声明方法:
  public class myCollection<T>
    {
        T[] myStack = new T[50];
    }

参数类T,放在<>中,它做为实际参数的占位符。编译器能识别T并用实际类型代替它
     myCollection<string> mc=new myCollection<string> ();//string是类型参数,它指定了这个类只处理string类型

尽管类可以是范型,不过它还是能限制所接受的类型:(为每个参数增加一个可选constraints列表,还要增加一个where关键字)
  public class myCollection<T> where T:IComparable
    {
        T[] myStack = new T[50];
    }

参数可以有多个接口约束,不过最多有一个类约束,另外有三个特殊约束需要注意:
class--参数必须是引用类型。
struct--参数必须是值类型。
new()--类型参数必须有一个无参数构造函数。
举个例子:
程序代码:
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication2
{
    public class GenStack<T>  //定义一个范型类,参数T是受限的,它必须是引用类型。
        where T : class
    {
        private T[] stackCollection;  //范型数组
        private int count = 0;
        public GenStack(int size)   //构造函数
        {
            stackCollection = new T[size]; //初始化参数
        }
        public void Add(T item)  //接受范型参数的方法
        {
            stackCollection[count] = item;
            count += 1;
        }
        public T this[int ndx]  //定义一个索引器来参数化成员属性
        {
            get
            {
                if (!(ndx < 0 || ndx > count - 1))
                {
                    return stackCollection[ndx];
                }
                else
                {
                    return (default(T));
                }
            }
        }
        public int ItemCount
        {
            get
            {
                return count;
            }
        }
        public int Compare<C>(T value, T value2)
        {
            return Comparer<T>.(value, value2);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            GenStack<string> myStack = new GenStack<string>(10);
            myStack.Add("BCCN");
            myStack.Add("CSDN");
            Console.WriteLine(myStack.ItemCount);
            Console.WriteLine(myStack[0]);
            int rel = ("BCCN", "CSDN");
            Console.WriteLine(rel.ToString());
            System.Threading.Thread.Sleep(10000);
        }
    }
}

运行结果:
图片附件: 游客没有浏览图片的权限,请 登录注册
2008-05-17 15:59
hebingbing
Rank: 6Rank: 6
来 自:黄土高坡
等 级:贵宾
威 望:27
帖 子:3417
专家分:371
注 册:2007-10-22
收藏
得分:0 
本来是想在说说事件和委托的,可是beniao兄弟写的《观察者模式——上班玩游戏,老总是怎么发现的》够经典了,不敢献丑,大家可以到下面地址去看看……
https://bbs.bccn.net/thread-213640-1-1.html
2008-05-17 16:23
快速回复:什么是接口?
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.021092 second(s), 10 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved