越想越迷糊了,到底什么时候用接口,什么时候用抽象类?
接口和抽象类的区别知道了,但实际应用中,到底如何选择呢?
其区别:
1:一个类可以实现任意多的接口,但是最多只能对一个抽象类进行子类化。
2:一个抽象类可以包括非抽象方法,而一个接口的所有方法在效果上都是抽象的。
3:一个抽象类可以申明并使用变量,而一个接口不行。
4:一个抽象类中的方法的访问修饰符可以使public,internal,protected,protected internal,private,而接口成员的访问修饰符在默认情况下都是public,而且,在申明接口成员时,不允许使用访问修饰符(甚至不能使用public)。
5:一个抽象类可以定义构造函数,而一个接口不行。
------解决方案--------------------一般来讲:像实体类就要用抽象类.而操作类就要用接口.
------解决方案--------------------1.抽象类是一个不完全的类,需要进一步专业化.接口只是一个行为的规范或规定;
2.接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法;
3.一个类一次可以实现若干个接口,但是只能扩展一个父类
4.接口可以用于支持回调,而继承并不具备这个特点.
如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单易行的方法来控制组件版本。通过更新基类,所有继承类都随更改自动更新。另一方面,接口一旦创建就不能更改。如果需要接口的新版本,必须创建一个全新的接口。
如果创建的功能将在大范围的全异对象间使用,则使用接口。
抽象类应主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。
如果要设计小而简练的功能块,则使用接口。
如果要设计大的功能单元,则使用抽象类。
如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。抽象类允许部分实现类,而接口不包含任何成员的实现。
------解决方案--------------------在这里我不想说太多的理论。
接口是规范,约定。
抽象类没有完全描述对象信息。
来看下例子。
需求,需要分析简历包括(中文,英文),给出伪代码
public class ChineseResume
{
public ChineseResume(){}
public ResumeDocument Parse(string text,string model)
{
ChineseRegex regex=new ChineseRegex();
ModelInfo modelInfo=regex.GetModelInfo(model);
TextDocument txt=new TextDocument(modelInfo);
TextInfo textInfo=txt.Parse();
if(textInfo!=null)
return new ResumeDocument(textInfo);
return new NothingResumeDocument();
}
}
public class EnglishResume
{
public EnglishResume(){}
public ResumeDocument Parse(string text,string model)
{
EnglishRegex regex=new EnglishRegex();
ModelInfo modelInfo=regex.GetModelInfo(model);
TextDocument txt=new TextDocument(modelInfo);
TextInfo textInfo=txt.Parse();
if(textInfo!=null)
return new ResumeDocument(textInfo);
return new NothingResumeDocument();
}
}
从对象角度分析,中文简历也好,英文简历也好都是简历,在运行时我不需要知道是中文还是英文,是简历就给我分析吧,很显然这两个类有大量的重复代码,应该抽象了。
public abstract Resume
{
public ResumeDocument Parse()
{
ModelInfo modelInfo=GetModelInfo();
TextDocument txt=new TextDocument(modelInfo);
TextInfo textInfo=txt.Parse();
if(textInfo!=null)
return new ResumeDocument(textInfo);
return new NothingResumeDocument();
}
public abstract ModelInfo GetModelInfo();
}
public class ChineseResume:Resume
{
private ChineseRegex regex=new ChineseRegex()
public ChineseResume(){}
public override ModelInfo GetModelInfo()
{
return regex.GetModelInfo();
}
}
英文简历也是一样。
假设我们有个插件平台,我需要将做好的对象加载到此平台中,但平台中中文和英文有很大不现体现时,接口显然很有用。
public class ChineseResume:Resume,IAddin,IResource
{
private ChineseRegex regex=new ChineseRegex()
public ChineseResume(){}
public override ModelInfo GetModelInfo()
{
return regex.GetModelInfo();
}
//..实现IAddin接口(平台加载和管理时需要)
//..实现IResource接口(平台对你要的资源进行管理,如文件,数据等等)
}
英文我不需要管理资源(假设没有资源)
public class EnglishResume:Resume,IAddin
{
private EnglishRegex regex=new EnglishRegex()
public EnglishResume(){}
public override ModelInfo GetModelInfo()
{
return regex.GetModelInfo();
}
//..实现IAddin接口(平台加载和管理时需要)