public struct Customer : IComparable{ private string _name; public Customer( string name ) { _name = name; } #region IComparable Members // IComparable.CompareTo() // 该方法在类型上不够安全。 // 必须检查参数right的运行时类型。 int IComparable.CompareTo( object right ) { if ( ! ( right is Customer ) ) throw new ArgumentException( "Argument not a customer", "right" ); Customer rightCustomer = ( Customer )right; return CompareTo( rightCustomer ); } // 类型安全的CompareTo。 // 其中right是一个Customer或者派生自Customer的类。 public int CompareTo( Customer right )我经常看到这种用法,对设计模式来说有什么用处,读书始终没有感觉到其中的奥秘,重新又定义了一方法个方法,重载了接口中
的方法
的方法
解决方案 »
- ASP.NET的正则表达式(数据验证)
- [ 新手求教]想在文本框中自动显示系统时间,写了个代码不运行
- 如何修改localhost:45865/demo.aspx这类网站使用的asp.net版本?
- wuyq11 最后解释一下下面这个函数,谢谢 //offset{left:xxx,top:xxx}
- 关于在.NET里实现IE里的后退功能,遇到奇怪现象
- 高手指点第二行是什么意思,我用vb.net不用C#
- **********问大家一个关于webclient问题,急呀!!!*********
- 工具箱里怎么添加组件?
- 一个关于CRYTAL REPORT的简单问题(请看下)
- 如何在客户端调用对话框?
- asp.net 站点跑不起来
- 如何通过CS文件从数据库读出的图片来设置网页的背景图片?
比如,FCL中有一个方法 Array.Sort()它里面的实现应该是这样的public void Sort() {
IComparable ic = this[0] as IComparable;
// 如果实现了接口,就调用接口方法
if(ic != null) {
int i = ic.CompareTo(this[1]);
...
} else {
// 这里采用默认的语言文化排序
}
}接口定义的好处在于,所有实现了某一接口的类都可以共享某一方法带来的好处。
public string this[int index]{}
object IList.this[int index]{}
}
为什么要用这样的用法,这是模式设计的一种,上面可能就是具体的应用
逻辑错误
接口没有 重载 这一说法
接口是用来实现的
你可以在自己的类中实现一个接口的方法或隐藏一个接口的方法
使用接口的好处
举个例子
我们需要编写一个数据表格控件,假设叫 SuperSuperGrid,它有一个属性 DataSource
用来接收绑定给这个表格的数据源
我们这样编写代码public [what] DataSource {
get;set;
}这里,我们应该接受一个什么类型的数据源呢?
为了通用性,我们不能把它定义为一个强类型,这样会导致不是这个类型的数据源但是符合绑定规则的数据源无法赋值
比如
假设 [what] 为 DataTable,那么我们就只能给他复制为一个 DataTable 或 DataTable 的派生类
当然,我们可以直接把 [what] 定为 object,这样的话,DataTable,DataSet都可以作为这个表格的数据源
但问题又出来了,这个表格确实能够接受 DataTable 和 DataSet,我们在代码里该如何处理呢,
我们怎么把 DataTable 或 DataSet 输出为相应的HTML呢?总不能 switch一下,case一堆吧
于是接口就出现了
我们事先定义一个接口,假设为 ISuperInterface
接口中有一个方法叫 ToHtml() 用来输出 html 表格
这样,所有的问题都解决了
最后的代码如下public class SuperSuperGrid : Control {
public object DataSource {
get {...} set {...}
} override render(HtmlTextWriter w) {
if(DataSource == null)
throw new ArgumentNullException("DataSource");
ISuperInterface isi = DataSource as ISuperInterface;
if(isi == null)
throw new Expeption("数据源必须实现接口ISuperInterface"); // 调用接口方法,输出HTML表格
w.Write(isi.ToHtml());
}
}
这接口的参数 是object 显然 会存在类型安全问题,
你传入的参数不是 Customer 是其他继承于 object 类的实例,那么编译器 是不能够检测的,只有运行的时候才会 发现错误,导致运行时的错误。
如果你 在实现接口的方法种调用
{
public int CompareTo( Customer right ) }
那么 编译器会检测 你调用接口的类型 是不是Customer 不是就会报错,所以避免了类型不安全的问题,
其实 跟 泛型的约束有些类似
public interfave ISuperInterface {
string ToHtml();
}
自己写一个类,这个类可以绑定到SuperSuperGridpublic sealed class SuperDataSource : ISuperInterface {
public string ISuperInterface.ToHtml() {
return "<table><tr><td>wfyfngu's super super grid</td></tr></table>";
}
}
在aspx页面使用这个Grid,假设ID为 superSuperGrid1superSuperGrid1.DataSource = new SuperDataSource();
我打下原话:
考虑通过显示接口实现接口成员来模拟
例如:为了创建强类型集合,IList实现会通常显示实现弱类型的成员,
并增加强类型的共有成员,以改变参数和返回值的类型
public class stringcollection :IList{
public string this[int index]{}
object IList.this[int index]{}
}
就是通过这个我想起了比较这个接口的例子,它就是这样用的,
我琢磨了很久没有理解
接口,跟你说深点吧,你晓得 什么叫框架把,什么叫类库把
框架是运行一些既定的步骤的东西,其中 有你些的代码
就拿ASP.NET 你写了一个Page类,但是没实现任何接口,
框架怎么跟你交付,框架怎么知道 你要实现的是什么东西,
所以你就必须实现 框架 要提供服务的接口,比如PAGE你要实现IhttpHandle
当框架运行时,如果你实现了 这个接口,那么 框架才会为你启动这个服务所以是框架调用你的东西,但是你的东西要满足框架的要求 即:实现既定的接口。其实这个跟 现实生活很多东西都是一样的,比如电脑吧,为什么你内存条插在主板上会工作,应为你满足了主板的要求所以....
你说的这个在一定的情况下
还不能体现出接口的所有特点
但有一点可以肯定
这个接口起到了规范 stringcollection 这个类的目的
而不需要项目经理告诉你,你必须在这个类里实现 Add() 方法
这里所谓的强类型集合指的是 stringcollection 只接受 string 类型的变量
而同时IList实现会通常显示实现弱类型的成员
指的是 Ilist.Add(object) 这个方法,换句话说,Ilist.Add接受任何派生自 object 的类型(C#中的所有类型)
考虑到 stringcollection 的需求
IList.Add(object) 这一方法应该被抛弃不用,我们可以申明一个新的Add(string)方法,这样就符合了stringcollection之接受string类型变量的目的,这也是接口的一个好处,可以隐藏接口的实现
参考下面的代码
public class stringcollection : Ilist {
void IList.Add(object value) {
// 这个方法因为没有显示声明访问性,所以在这个方法的调用者看来,这是个private方法
} public void Add(string value) {
// TODO: 在这里添加代码逻辑
}
}
你知道DataGridView.DataSouce为啥能绑DataSet,DataTable,Ilist<T> Arraylist-------等等那么多不同继承体系的对象都可以绑定,你就从来就不曾疑惑和感叹他的强大原因:虽然他们是不同继承体系,但他们都实现相同的接口所以对于DataGridView.DataSouce来说,我不管你们是如何继承和实现滴,但你要给我实现一个同样的接口
LZ 三思: 针对 参数是object的 你是对的
如果参数非object 比如是int,等 就没必要
我尽量说通俗一点吧,希望你能懂。比如你要插入一条数据。你原先是用到一个DogSqlProvider的类,它有个函数
public void Insert(Dog d)
{
...
}你的代码是这样写的
DogSqlProvider dogProvider = new DogSqlProvider();
dogProvider.Insert(d);现在客户提出新的要求:“我们要用Oracle数据库”,于是你就添加了一个DogOracleProvider的类,同样它也有个void Insert(Dog d)函数。
而且要把原先的代码改成
DogOracleProvider dogProvider = new DogOracleProvider();
dogProvider.Insert(d);这样接下来又有客户说,“我们要用XML存储”“我们只用Access的”,你是不是还要一次次修改Code?
如果客户说:“你不要管我们具体怎么插入数据,这件事情我们自己做”呢?
这时候接口的作用就体现出来了,你把最初的代码写成:IDogProvider dogProvider = DataFactory.CreateDogProvider();
dogProvider.Insert(d);
然后封装成起来,而接下数据怎么插入就不关你的事了,只要所有继承了IDataProvider的类都可以调用,用户用户想怎么插它只要添加一个继承IDataProvider的类,并让DataFactory调用这个类就可以了(这里通常用配置文件直接配置)于是到后来你的数据层可能有DogSqlProvider,DogOracleProvider,DogXmlProvider, DogAccessProvider这些类或者更多,你只要改下配置文件就可以选择用那种插入数据方式,而不需要改动封装在业务层的代码了。
woaixueyu我不太明白你这句话的意思?能再给我说说吗?谢谢
woaixueyu我不太明白你这句话的意思?能再给我说说吗?谢谢