2016年6月19日
23:46
Main Interfaces & Delegates 接口和委托
1.接口基本语法
public interface IList : ICollection, IEnumerable { int Add (object value); // methods bool Contains (object value); ... bool IsReadOnly { get; } // property ... object this [int index] { get; set; } // indexer }
接口相当于一个抽象类,只有签名没有实现;
Interface = purely abstract class; only signatures, no implementation.
接口可能包含方法、属性、索引器、时间(没有字段、没有常量、没有构造函数、没有析构函数、没有运算符、没有级联类型)
May contain methods, properties, indexers and events
(no fields, constants, constructors, destructors, operators, nested types).
接口成员隐藏着abstract或者virtual关键字
Interface members are implicitly public abstract (virtual).
接口成员不能为static
Interface members must not be static.
接口可以继承自其他的接口
Interfaces can inherit from other interfaces.
类和结构体可以实现多个接口
Classes and structs may implement multiple interfaces.
2.Implemented by Classes and Structs类、结构体实现接口
class MyClass : MyBaseClass, IList, ISerializable { public int Add (object value) {...} public bool Contains (object value) {...} ... public bool IsReadOnly { get {...} } ... public object this [int index] { get {...} set {...} } }
一个类只能继承一个类但是可以实现多个接口
A class can inherit from a single base class, but can implement multiple interfaces.
一个结构体不能继承自其他的类或者结构体但是可以实现多个接口
A struct cannot inherit from any type, but can implement multiple interfaces.
接口中的每一个成员必须被实现
Every interface member (method, property, indexer) must be implemented or inherited from a base class.
实现接口内部包含的方法不必要声明为override
Implemented interface methods need not be declared as override.
实现接口内部包含的方法可以声明为abstract抽象方法
Implemented interface methods can be declared as abstract (i.e. an interface can be implemented by an abstract class).
如果子类MyClass中Add方法应该被重写那么应当声明为virtual尽管在IList中已经隐藏着virtual关键字
If Add() should be overridden in a subclasses of MyClass it must be declared as virtual (although Add() is already implicitly virtual in IList).
3.Working with Interfaces
举例:
interface ISimpleReader { int Read(); } interface IReader : ISimpleReader { void Open(string name); void Close(); } class Terminal : ISimpleReader { public int Read() { ... } } class File : IReader { public int Read() { ... } public void Open(string name) { ... } public void Close() { ... } } ISimpleReader sr = null; // null can be assigned to any variable of an interface type sr = new Terminal(); sr = new File(); IReader r = new File(); sr = r;
4.Delegate委托
声明委托:delegate void Notifier (string sender);//组成:普通函数的签名加上关键字delegate
声明委托变量:Notifier greeting;
将方法分配给委托变量:
void SayHello(string sender) { Console.WriteLine("Hello from " + sender); } greetings = new Notifier(SayHello); // or just: greetings = SayHello; // since C# 2.0
调用委托变量:greeting("John");
5.不同的方法分配
每一个方法可以分配至一个委托变量:
void SayGoodBye(string sender) { Console.WriteLine("Good bye from " + sender); } greetings = SayGoodBye; greetings("John"); // SayGoodBye("John") => "Good bye from John"
注意:委托变量可以被赋予null值;
如果委托变量为null,那么该委托变量不能被调用,否则产生异常;
委托变量其实是一种类,可以存储的数据结构中,可以传递参数
Creating a Delegate Value:
m = obj.Method; // or in long form: m = new DelegateType (obj.Method);
一个委托变量可以存储一个方法以及它的接收器,不是参数:greetings = myObj.SayHello;
如果obj是this那么可以省略:greetings = SayHello;
方法可以是静态的,但是这样需要用类名来进行实例,greetings = MyClass.StaticSayHello;
方法不能是抽象的,但是可以使virtual,override,new
方法的签名必须和委托的签名相匹配
有相同的参数个数;
有相同的参数类型,包括返回类型;
有相同的参数修饰符(value,ref/out)
6.多播委托Multicast Delegates
一个委托变量可以同时掌握着多个方法;
Notifier greetings; greetings = SayHello; greetings += SayGoodBye; greetings("John"); // "Hello from John" // "Good bye from John" greetings -= SayHello; greetings("John"); // "Good bye from John"
注意:
如果多播委托是一个函数,那么返回值是最后一个被调用的那个方法;
如果多播委托是out修饰的参数类型,那么参数应该是最后一个调用的返回.ref修饰的参数类型应该从所用的方法一直传递下去。
Java中实现上述功能:
7.事件
事件就是特殊的委托域;
事件与委托变量不同的地方:
只有声明事件的类才能够解除事件;
其他类只能改变事件域只能使用+= 或者 -=
class Model { public event Notifier notifyViews; public void Change() { ... notifyViews("Model"); } } class View { public View(Model m) { m.notifyViews += Update; } void Update(string sender) { Console.WriteLine(sender + " was changed"); } } class Test { static void Main() { Model model = new Model(); new View(model); new View(model); ... model.Change(); } }
事件在.NET Library中如何处理
举例:
public delegate void KeyEventHandler (object sender, KeyEventArgs e); public class KeyEventArgs : EventArgs { public virtual bool Alt { get {...} } // true if Alt key was pressed public virtual bool Shift { get {...} } // true if Shift key was pressed public bool Control { get {...} } // true if Ctrl key was pressed public bool Handled { get{...} set {...} } // indicates if event was already handled public int KeyValue { get {...} } // the typed key code ... } class MyKeyEventSource { public event KeyEventHandler KeyDown; ... KeyDown(this, new KeyEventArgs(...)); ... } class MyKeyListener { public MyKeyListener(...) { keySource.KeyDown += HandleKey;} void HandleKey (object sender, KeyEventArgs e) {...} }