using System;namespace ConsoleApplication1 { /// <summary> /// Class1 的摘要说明。 /// </summary> public interface I { void Func(); }
class A :I { public virtual void Func() { Console.WriteLine("FuncA"; } }
class B : A , I //注意这里的意思? { public void Func() { Console.WriteLine("FuncB";} }
class C : A { public override void Func() { Console.WriteLine("FuncC";} } class Class1 { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { I a = new A() ; //申明了接口a,并马上和一个类的实例发生关系了 I b = new B() ; //申明了接口b,并马上和一个类的实例发生关系了 I c = new C() ; //申明了接口c,并马上和一个类的实例发生关系了 a.Func() ; //检查a的实例A, 发现A和接口I捆绑了,所以执行A的函数Func ,结果: FuncA b.Func() ; //检查b的实例B, 发现B和接口I捆绑了,所以执行B的函数Func ,结果: FuncB c.Func() ; //家常c的实例C,发现其没有和接口I捆绑,系统继续找它的父类. 发现A和I捆绑了,他就去找函数A,发现A是虚拟函数,系统又从头来找类的实例C,发现C重载(override)了Func,好了,马上执行该函数. 结果是FuncC; Console.ReadLine(); } } }
看完上面的,照着下面的例子抄俩边,保证你学会。 --------------------------------- using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data;namespace Events_Interfaces { public delegate void dele();//声明代表 delegate 关键字通知编译器 dele 是一个委托类型 public interface IEvents //定义接口IEvents,包含方法FireEvent事件event1 { event dele event1; void FireEvent(); } public class Form1 : System.Windows.Forms.Form { private System.Windows.Forms.Label label1; private System.Windows.Forms.TextBox textBox1; private System.Windows.Forms.Label label2; private System.Windows.Forms.Button button1; private System.Windows.Forms.Label label3;private System.ComponentModel.Container components =null;public Form1() { InitializeComponent(); }protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); }#region Windows Form Designer generated codeprivate void InitializeComponent() { this.textBox1 = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.button1 = new System.Windows.Forms.Button(); this.label2 = new System.Windows.Forms.Label(); this.label3 = new System.Windows.Forms.Label(); this.SuspendLayout();this.textBox1.Location = new System.Drawing.Point(8, 80); this.textBox1.Name = "textBox1"; this.textBox1.Size = new System.Drawing.Size(56,23); this.textBox1.TabIndex = 1; this.textBox1.Text = ""; this.textBox1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Key_Press);this.label1.Location = new System.Drawing.Point(16, 16); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(256,64); this.label1.TabIndex = 0; this.label1.Text = "Whenever you use the arrow keys inside the text box, Corresponding events will be" +"fired to display the label appropriately. Have a try!!";this.button1.Location = new System.Drawing.Point(240, 112); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(48,23); this.button1.TabIndex = 3; this.button1.Text = "Exit"; this.button1.Click += new System.EventHandler(this.button1_Click); // // label2 // this.label2.Location = new System.Drawing.Point(88, 80); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(184,23); this.label2.TabIndex = 2; this.label2.TextAlign =System.Drawing.ContentAlignment.MiddleCenter; // // label3 // this.label3.Location = new System.Drawing.Point(8, 104); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(64,23); this.label3.TabIndex = 4; this.label3.TextAlign =System.Drawing.ContentAlignment.MiddleCenter; // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(6, 16); this.ClientSize = new System.Drawing.Size(292,141); this.Controls.AddRange(new System.Windows.Forms.Control[] {this.label3,this.button1,this.label2,this.textBox1,this.label1});this.Font= new System.Drawing.Font("Comic SansMS",8.25F,System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,((System.Byte)(0))); this.Name = "Form1"; this.Text = "Events"; this.ResumeLayout(false); } #endregionstatic void Main() { Application.Run(new Form1()); }private void Key_Press(object sender, System.Windows.Forms.KeyEventArgs e) { textBox1.Text = ""; label2.Text = ""; string keyId = e.KeyCode.ToString(); switch (keyId)//判断是否按下方向键 { case "Right": label3.Text = ""; IEvents id1 = new EventClass1(); //实例化一个接口 id1.event1 += new dele(EventFired1);//定义EventClass1中的事件响应方法 id1.FireEvent();//调用EventClass1中的FireEvent方法,触发event1 事件,事件调用EventFired1方法 break; case "Left": label3.Text = ""; IEvents id2 = new EventClass2(); id2.event1 += new dele(EventFired2); id2.FireEvent(); break; case "Down": label3.Text = ""; IEvents id3 = new EventClass3(); id3.event1 += new dele(EventFired3); id3.FireEvent(); break; case "Up": label3.Text = ""; IEvents id4 = new EventClass4(); id4.event1 += new dele(EventFired4); id4.FireEvent(); break; default: label3.Text = keyId; break; } } //EventFired1方法 public void EventFired1() { label2.Text = ""; label2.Text = "You pressed RIGHT arrow key"; } public void EventFired2() { label2.Text = ""; label2.Text = "You pressed LEFT arrow key"; } public void EventFired3() { label2.Text = ""; label2.Text = "You pressed DOWN arrow key"; } public void EventFired4() { label2.Text = ""; label2.Text = "You pressed UP arrow key"; }private void button1_Click(object sender, System.EventArgs e) { Application.Exit(); } } public class EventClass1 : IEvents { public event dele event1; public void FireEvent() { event1(); } } public class EventClass2 : IEvents { public event dele event1; public void FireEvent() { event1(); } } public class EventClass3 : IEvents { public event dele event1; public void FireEvent() { event1(); } } public class EventClass4 : IEvents//EventClass1继承接口IEvents { public event dele event1;//定义事件成员event1 //当事件发生时 public void FireEvent() { event1();//调用事件处理 } }}
{
手机号;
}
而了使各个层间通信正常,使用接口是很有必要的,这样N个人可以分别开发,只要接口一致就可以保证模块间交互正常.
如果是一个人开发的东西,一般没有使用接口的必要,不过如果程序比较复杂,使用接口可以使程序层次清晰.
public interface opeTable
{
SqlDataReader GetDataReader(string asDr);
bool CloseConn();
}
下面實現接口中的方法
public class OperateTable,opeTable
{
public SqlDataReader GetDataReader(string asDr)
{
SqlDataReader sqlDr ;
if (asDr.Length >= 0)
{
sqlDr = odbOperate.GetDr(asDr);
}
else
{
sqlDr = null;
}
return sqlDr;
} public bool CloseConn()
{
bool bConn = false;
try
{
odbOperate.CloseConn();
bConn = true;
}
catch(Exception e)
{
bConn = false;
throw e;
}
return bConn;
}
}
你开个杂货店,刚开始做生意时,由于买的东西较少,所以什么物品都堆在一起,别人买什么你就从中扒出来买。
后来你感觉这种方法非常不爽,每次扒来扒去太麻烦了,于是你把不同的产品放在不同的地方,如:厨房用品,洗衣用品等,更好的就用个货架把他们分开;这样若别人要个洗衣粉什么的,就直接去洗衣用品去拿就OK了。
再后来就如现在的超市,分类越来越细,厨房用品->>锅碗瓢盆,每个又都分别放在一个小货架,相要什么,直接去拿就OK了,省得想买个菜刀还满超市跑。接口也类似上面的管理概念;当然把所有的货物全部椎放到你的门头去买也可以,但在一定情况下,你不会竟争过超市,当然你也可以在程序中把所有的功能都在类中实现,而不用接口,但在较大的项目中,扒来扒去找需要的功能类,自己都感觉烦!
我想从南京到上海,不同的人可能有不同的走法.我们就定义一个接口:
public interface NJtoSH
{
void Go();
}张三可能坐汽车.
李四可能坐飞机.
...public class ZS : NJtoSH
{
public void Go()
{
ByBus();
}
private void ByBus()
{
}
}public class LS : NJtoSH
{
public void Go()
{
ByPlane();
}
private void ByPlane()
{
}
}
-------------------
简单的说接口就是一个契约或者规范.比如遥控器,国家出台了一个国家遥控器规范,明文要求所有的遥控器厂家都要遵循这个规范,如果不遵循规范就不给3C认证标志,就不允许上市出卖..为什么要这个规范呢?大家在时间生活中会经常碰到,甲厂的遥控器不能遥控乙厂的电视,电视遥控器不能遥控其它电器如空调,冰箱.!原因是什么呢?是各个遥控器都没有遵循一个规范,电波有长有短,电压有高有低,导致各自为政,4分5列!
可以想像出国家遥控器标准只是是规定遥控器的一些重要技术指标,比如要发射波应该多长,电压应该多高,...,但它绝对不会规范出遥控器的材质,形状,重量和颜色,也是说规范把所有同遥控无关的东西都抛弃了!每个遥控器厂家只要遵循了规范,那么对遥控器可以有任意的诠释.比如A厂可以用铁做,牢固无比,B厂可以用纸,可以任意折叠,anyway,不管用什么做,做出什么样子,只要遵循规范的遥控器就可以遥控所有的电器(当然电器厂家也要遵循一定的规范),甚至可以遥控导弹发射!利害吧,这就是接口的威力.
再详细点,接口就是一个规范,他和具体的实现无关!接口是规范(虚的),他只是一张纸,也是说在实际的使用中接口只有依托一个实现了它的类的实例,才会有意义,如上面的各个厂家做的遥控器产品.每个实现接口的类(厂家)必需实现接口中所有的功能. 一旦一个类实现了一个接口,就可说一个类和接口捆绑了(这个很重要,做题目的时候会用到)
来个例子
interface 遥控器规范 //国家定义的遥控器规范 ,每个遥控器厂家必需实现(诠释)它
{
int 波长();
int 电压();
}
class 甲厂铁遥控器 : 遥控器规范 //甲厂的遥控器实现(诠释)了这个规范,它和遥控器规范捆绑了!好,它可以在市场上出售了
{
public int 波长(); //规范上定义的指标
public int 电压(); //规范上定义的指标
public int 形状() { 正方形}; //甲厂自己对该产品的诠释
public int 材质() ( 铁 }; //甲厂自己对该产品的诠释
}
class 乙厂纸遥控器 : 遥控器规范 ////甲厂的遥控器实现(诠释)了这个规范,它和遥控器规范捆绑了!好,它可以在市场上出售了
{
public int 波长(); ////规范上定义的指标
public int 电压(); //规范上定义的指标
public int 形状()( 圆形); //甲厂自己对该产品的诠释,是圆形
public int 材质()( 纸); //甲厂自己对该产品的诠释,用纸做,好酷!
}
class 电器
{
procedure 接收遥控(遥控器规范 //电器上,接收遥控指令
{.....
接收(遥控器规范.波长) ;
接收(遥控器规范.电压);
.....}
}
static main()
{
甲厂铁遥控器 ControlA ; //申明控制器对象
乙厂纸遥控器 ControlB ;
ControlA = new 甲厂铁遥控器(); //实例化控制器对象,这个时候系统在托管堆中为该对象分配了空间
ControlB = new 乙厂纸遥控器() ;
遥控器规范 ControlInterfaceA = (遥控器规范)遥控器1 ; //把对象实例转换成一个规范,为什么呢?因为"我家的电器".只能识别遥控器规范,它识别不到具体的遥控器
遥控器规范 ControlInterfaceB = (遥控器规范)遥控器2; //同上
电器 我家的电器 = new 电器();
我家的电器.接收遥控(ControlInterfaceA) //我用甲厂遥控器遥控我家的电器. 注意: 这里的ControlInterfaceA是不能单独存在的,它必要依赖实现了"遥控器规范"的类的实例"ControlA".道理很简单,接口是一个指针,不会被分配空间,你就无法使用,只有和一个具体类的实例联系了,才有了可以活跃空间.
我家的电器.接收遥控(ControlInterfaceB) //我用乙厂遥控器遥控我家的电器
...
//下面是我的的想像,我可以用遥控器来控制导弹发射!
我的导弹.接收遥控(ControlInterfaceA);
我的导弹.接收遥控(ControlInterfaceB);
...
}
--------------------------------------------------------------------
接口的执行
好了,有了接口的概念,再来谈c#程序在运行中是如何使用接口的,如何访问接口函数.具体流程如下
a.当调用一个接口的函数时,系统会去检查这个接口对应实例是什么?
b.找到这个实例后,再去找这个实例对应的实例类是什么(什么是实例类,参看读书笔记二)
c.根据这个实例类去检查该实例类是否和接口发生了捆绑(看是否实现了该接口,冒号后面就是)
d.好!如果实例类实现了该接口(发生了捆绑) ,它就在这个实例类中找函数的定义.然后执行该函数.执行结束.
e.如果没找到,他就继续往父类找,直到找到第一个和接口捆绑的父类为止
f.找到后,它再检查该函数是否是虚拟函数,
g.如果不是,他马上就执行它 .
h 如果是,麻烦了,系统又要从头来过,去检查该实例类的函数是否重载了该函数,...具体过程见(c#读书笔记2).
例子:
using System;namespace ConsoleApplication1
{
/// <summary>
/// Class1 的摘要说明。
/// </summary>
public interface I
{
void Func();
}
class A :I
{
public virtual void Func()
{
Console.WriteLine("FuncA";
}
}
class B : A , I //注意这里的意思?
{
public void Func() { Console.WriteLine("FuncB";}
}
class C : A
{
public override void Func() { Console.WriteLine("FuncC";}
} class Class1
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
I a = new A() ; //申明了接口a,并马上和一个类的实例发生关系了
I b = new B() ; //申明了接口b,并马上和一个类的实例发生关系了
I c = new C() ; //申明了接口c,并马上和一个类的实例发生关系了
a.Func() ; //检查a的实例A, 发现A和接口I捆绑了,所以执行A的函数Func ,结果: FuncA
b.Func() ; //检查b的实例B, 发现B和接口I捆绑了,所以执行B的函数Func ,结果: FuncB
c.Func() ; //家常c的实例C,发现其没有和接口I捆绑,系统继续找它的父类. 发现A和I捆绑了,他就去找函数A,发现A是虚拟函数,系统又从头来找类的实例C,发现C重载(override)了Func,好了,马上执行该函数. 结果是FuncC;
Console.ReadLine();
}
}
}
---------------------------------
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;namespace Events_Interfaces
{
public delegate void dele();//声明代表 delegate 关键字通知编译器 dele 是一个委托类型
public interface IEvents //定义接口IEvents,包含方法FireEvent事件event1
{
event dele event1;
void FireEvent();
}
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Label label3;private System.ComponentModel.Container components =null;public Form1()
{
InitializeComponent();
}protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}#region Windows Form Designer generated codeprivate void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.button1 = new System.Windows.Forms.Button();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.SuspendLayout();this.textBox1.Location = new System.Drawing.Point(8, 80);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(56,23);
this.textBox1.TabIndex = 1;
this.textBox1.Text = "";
this.textBox1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Key_Press);this.label1.Location = new System.Drawing.Point(16, 16);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(256,64);
this.label1.TabIndex = 0;
this.label1.Text = "Whenever you use the arrow keys inside the text box, Corresponding events will be" +"fired to display the label appropriately. Have a try!!";this.button1.Location = new System.Drawing.Point(240, 112);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(48,23);
this.button1.TabIndex = 3;
this.button1.Text = "Exit";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// label2
//
this.label2.Location = new System.Drawing.Point(88, 80);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(184,23);
this.label2.TabIndex = 2;
this.label2.TextAlign =System.Drawing.ContentAlignment.MiddleCenter;
//
// label3
//
this.label3.Location = new System.Drawing.Point(8, 104);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(64,23);
this.label3.TabIndex = 4;
this.label3.TextAlign =System.Drawing.ContentAlignment.MiddleCenter;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 16);
this.ClientSize = new System.Drawing.Size(292,141);
this.Controls.AddRange(new System.Windows.Forms.Control[] {this.label3,this.button1,this.label2,this.textBox1,this.label1});this.Font= new System.Drawing.Font("Comic SansMS",8.25F,System.Drawing.FontStyle.Regular,
System.Drawing.GraphicsUnit.Point,((System.Byte)(0)));
this.Name = "Form1";
this.Text = "Events";
this.ResumeLayout(false);
}
#endregionstatic void Main()
{
Application.Run(new Form1());
}private void Key_Press(object sender,
System.Windows.Forms.KeyEventArgs e)
{
textBox1.Text = "";
label2.Text = "";
string keyId = e.KeyCode.ToString();
switch (keyId)//判断是否按下方向键
{
case "Right":
label3.Text = "";
IEvents id1 = new EventClass1(); //实例化一个接口
id1.event1 += new dele(EventFired1);//定义EventClass1中的事件响应方法
id1.FireEvent();//调用EventClass1中的FireEvent方法,触发event1 事件,事件调用EventFired1方法
break;
case "Left":
label3.Text = "";
IEvents id2 = new EventClass2();
id2.event1 += new
dele(EventFired2);
id2.FireEvent();
break;
case "Down":
label3.Text = "";
IEvents id3 = new EventClass3();
id3.event1 += new
dele(EventFired3);
id3.FireEvent();
break;
case "Up":
label3.Text = "";
IEvents id4 = new EventClass4();
id4.event1 += new
dele(EventFired4);
id4.FireEvent();
break;
default:
label3.Text = keyId;
break;
}
}
//EventFired1方法
public void EventFired1()
{
label2.Text = "";
label2.Text = "You pressed RIGHT arrow key";
}
public void EventFired2()
{
label2.Text = "";
label2.Text = "You pressed LEFT arrow key";
}
public void EventFired3()
{
label2.Text = "";
label2.Text = "You pressed DOWN arrow key";
}
public void EventFired4()
{
label2.Text = "";
label2.Text = "You pressed UP arrow key";
}private void button1_Click(object sender,
System.EventArgs e)
{
Application.Exit();
}
}
public class EventClass1 : IEvents
{
public event dele event1;
public void FireEvent()
{
event1();
}
}
public class EventClass2 : IEvents
{
public event dele event1;
public void FireEvent()
{
event1();
}
}
public class EventClass3 : IEvents
{
public event dele event1;
public void FireEvent()
{
event1();
}
}
public class EventClass4 : IEvents//EventClass1继承接口IEvents
{
public event dele event1;//定义事件成员event1
//当事件发生时
public void FireEvent()
{
event1();//调用事件处理
}
}}
老板从来不会管今天这个文件如何送到某个部门,也不会关心事情处理细节。老板不是全能的,也没有这个精力。老板只会说,Actor1,去报税,Actor2,去收帐。报税、收帐就是接口。具体如何执行这些,Actor才需要去做。这样老板才可以管理公司,而不是具体的只能管具体的某个人,而是这样的一类人都可以。……
用抽象解释抽象,可能更抽象。奸笑
如果你的Oracle类和Sql Server类使用同一个接口
那么你的WebService就不必关心后台使用的数据库类型