举个最简单例子吧.假如有个构建SQL语句的类.它有一个方法获得任意字符通配符.为此,我们写个抽象类: public abstract class DbFactoryBase { //默认实现,通配符 public virtual string GetMultiLikeChar() { return "%"; } } //我们写MSSQL的实现 public class SqlSvrFactory:DbFactoryBase { //GetMultiLikeChar方法不需要重载 } //我们写Jet的实现 public class JetFactory:DbFactoryBase { //重载,通配符 public override string GetMultiLikeChar() { return "*"; } } 好处是显而易见的,抽象类提供了默认实现,子类只在需要更改的时候才重载这个方法,我们这个类可以很容易扩展,比如增加对ORACLE的实现,调用这个抽象类的代码也不需要改变,但返回来的字符已经不同了.代码看上去也更简洁...等等.这只是冰山之一角.建议多看看模式之类的书.
好比说你要开发一个适合三种不同数据库的应用程序public class DataAccessFactory { private DataAccessFactory() { }
public static IDataAccess CreateDataAccess() { string type = System.Configuration.ConfigurationSettings.AppSettings["DataType"].ToString(); switch(type) { case "OLEDB": return (IDataAccess)(new OledbDataAccess()); break; case "MSSQL": return (IDataAccess)(new MsSqlDataAccess()); break; case "ORACLE": return (IDataAccess)(new OracleDataAccess()); break; } } }public interface IDataAccess { bool ExcuteCommand(string cmd); } public class OledbDataAccess : IDataAccess { public bool ExcuteCommand(string cmd) { return true; } } public class MsSqlDataAccess : IDataAccess { public bool ExcuteCommand(string cmd) { return true; } } public class OracleDataAccess : IDataAccess { public bool ExcuteCommand(string cmd) { return true; } } public class UseData { //未使用接口 public bool Excute1(string cmd) { string type = System.Configuration.ConfigurationSettings.AppSettings["DataType"].ToString(); switch(type) { case "OLEDB": OledbDataAccess da = new OledbDataAccess(); da.ExcuteCommand(cmd); break; case "MSSQL": MsSqlDataAccess da = new MsSqlDataAccess(); da.ExcuteCommand(cmd); break; case "ORACLE": OracleDataAccess da = new OracleDataAccess(); da.ExcuteCommand(cmd); break; } } //使用接口 public bool Excute2(string cmd) { IDataAccess da = DataAccessFactory.CreateDataAccess(); da.ExcuteCommand(cmd); } }不使用接口每次做数据操作的时候都需要判断数据库类型然后生成相应实例,使用接口的程序只需要在一个地方判断类型即可
对于一个抽象类,至少一个方法是抽象方法既可,这意味着它也可以具有具体方法[译注:Concrete Method,这只是相对于抽象方法而言,面向对象中并没有这个概念]。
对于一个接口,所有的方法必须都是抽象的。
实现了一个接口的类必须为接口中的所有方法提供具体的实现,否则只能声明为抽象类。
在C#中,多重继承(Multiple Inheritance)只能通过实现多个接口得到。抽象类只能单继承[注:C#中的单继承是指所有类作为基类的时候都只能是派生类声明中唯一的基类,而不仅仅是抽象类]。
接口定义的是一个契约,其中只能包含四种实体,即方法、属性、事件和索引器。因此接口不能包含常数(Constant)、域、操作符、构造器、析构器、静态构造器或类型[译注:指嵌套的类型]。
同时,一个接口还不能包含任何类型的静态成员。修饰符abstract、public、protected、internal、private、virtual、override都是不允许出现的,因为它们在这种环境中是没有意义的。
类中实现的接口成员必须具有公有的可访问性。
其次,看看多层开发架构的一些例子;再举个例子:如果你是想机器人做事情,是直接叫他去做好还是给一个提纲给他好?软件设计中有一句话叫“从接口开始”;
CSDN小助手 是一款脱离浏览器也可以使用csdn论坛的
软件!
界面: http://qqwwee.com/
下载: http://qqwwee.com/csdn.rar 包含源代码
你是宁愿写个函数每次ButtonClick的时候凋用还是
宁愿同样的代码在3个ButtonClick里都敲一遍呢
1.接口规范性举例
public string InsertValue(System.Collections.IList list,object o)
{
list.Add(o);
}
InsertValue方法并不关心list是什么类,由什么人实现的,只要list实现了IList接口就肯定会有Add这个方法.2.接口灵活性举例
以下两个方法,前者用接口,后者用具体实现的类,很显然,用接口作为参数更灵活,只要实现了IList接口的类都可以作为参数带进去
public string GetMaxValue(System.Collections.IList list)
{
}public string GetMaxValue(System.Collections.ArrayList list)
{
}
public abstract class DbFactoryBase
{
//默认实现,通配符
public virtual string GetMultiLikeChar()
{
return "%";
}
}
//我们写MSSQL的实现
public class SqlSvrFactory:DbFactoryBase
{
//GetMultiLikeChar方法不需要重载
}
//我们写Jet的实现
public class JetFactory:DbFactoryBase
{
//重载,通配符
public override string GetMultiLikeChar()
{
return "*";
}
}
好处是显而易见的,抽象类提供了默认实现,子类只在需要更改的时候才重载这个方法,我们这个类可以很容易扩展,比如增加对ORACLE的实现,调用这个抽象类的代码也不需要改变,但返回来的字符已经不同了.代码看上去也更简洁...等等.这只是冰山之一角.建议多看看模式之类的书.
{
private DataAccessFactory()
{
}
public static IDataAccess CreateDataAccess()
{
string type = System.Configuration.ConfigurationSettings.AppSettings["DataType"].ToString();
switch(type)
{
case "OLEDB":
return (IDataAccess)(new OledbDataAccess());
break;
case "MSSQL":
return (IDataAccess)(new MsSqlDataAccess());
break;
case "ORACLE":
return (IDataAccess)(new OracleDataAccess());
break;
}
}
}public interface IDataAccess
{
bool ExcuteCommand(string cmd);
} public class OledbDataAccess : IDataAccess
{
public bool ExcuteCommand(string cmd)
{
return true;
}
} public class MsSqlDataAccess : IDataAccess
{
public bool ExcuteCommand(string cmd)
{
return true;
}
} public class OracleDataAccess : IDataAccess
{
public bool ExcuteCommand(string cmd)
{
return true;
}
} public class UseData
{
//未使用接口
public bool Excute1(string cmd)
{
string type = System.Configuration.ConfigurationSettings.AppSettings["DataType"].ToString();
switch(type)
{
case "OLEDB":
OledbDataAccess da = new OledbDataAccess();
da.ExcuteCommand(cmd);
break;
case "MSSQL":
MsSqlDataAccess da = new MsSqlDataAccess();
da.ExcuteCommand(cmd);
break;
case "ORACLE":
OracleDataAccess da = new OracleDataAccess();
da.ExcuteCommand(cmd);
break;
}
} //使用接口
public bool Excute2(string cmd)
{
IDataAccess da = DataAccessFactory.CreateDataAccess();
da.ExcuteCommand(cmd);
}
}不使用接口每次做数据操作的时候都需要判断数据库类型然后生成相应实例,使用接口的程序只需要在一个地方判断类型即可
不过楼主似乎还是不满意,呵呵
class Rectangle
{
void Draw()
{
//
}
}
class Line
{
void Draw()
{
//
}
}
class Ellipse
{
void Draw()
{
//
}
}
绘制时
for(int i=0;i<array.Count;i++)
{
if(array[i] is Rectangle)
{
(array[i] as Rectangle).Draw();
}
else if(array[i] is Line)
{
(array[i] as Line).Draw();
}
else if(array[i] is Ellipse)
{
(array[i] as Ellipse).Draw();
}
}2、 定义接口和抽象类时
abstract class Shape
{
void Draw();
}
class Rectangle :Shape
{
void Draw()
{
//
}
}
class Line :Shape
{
void Draw()
{
//
}
}
class Ellipse :Shape
{
void Draw()
{
//
}
}
使用时:
for(int i=0;i<array.Count;i++)
{
(array[i] as Shape).Draw();
}已经可以看到差别了。如果你要支持更多的图形和更多的功能,差别就明显了。可能你会想不用抽象类也可以实现。可是你怎么实现Shape这个类的Draw方法。Shape本身就是个抽象的概念。你不会希望谁创建了一个Shape实例吧。类似的如“动物”是个抽象类。有类别(哺乳类,两栖类等)等属性,有吼叫等方法。这些都需要一个抽象类来定义。如果没有抽象类,你打算怎么来实现?书上也有很多这样的例子。讲解的也很详细。(以上的例子也源于一本书,忘记书名了~)。
抽象和接口不仅限于此。需要在实践中不断总结。