抽象类
时间:2010-10-29 来源:infi
抽象方法不能实例化。这样做[译注:指实例化一个抽象类]是不合逻辑的,因为那些抽象成员没有实现。那么,不能实例化一个类有什么好处呢?很多!抽象类稳坐类继承树的顶端。它们确定了类的结构和代码的意图。用它们可以得到更易搭建的框架。这是可能的,因为抽象类具有这个框架中所有基类的一般信息和行为。看看下面的例子:
abstract public class Contact { // 抽象类Contact
protected string name;
public Contact() {
// 语句
}
public abstract void generateReport();
abstract public string Name {
get;
set;
}
}
Contact是一个抽象类。Contact有两个抽象成员,其中有一个是抽象方法,名为generateReport()。这个方法使用了abstract修饰符进行声明,这个声明没有实现(没有花括号)并以分号结束。属性Name也被声明为抽象的。属性访问器也是以分号结束。
public class Customer : Contact { // Customer继承自抽象类Contact
string gender;
decimal income;
int nuberOfVisits;
public Customer() {
// 语句
}
public override void generateReport() {
// 产生一份独特的报告
}
public override string Name {
get {
numberOfVisits++;
return name;
}
set {
name = value;
nuberOfVisits = 0;
}
}
}
public class SiteOwner : Contact {
int siteHits;
string mySite;
public SiteOwner() {
// 语句
}
public override void generateReport() {
// 产生一份独特的报告
}
public override string Name {
get {
siteHits++;
return name;
}
set {
name = value;
siteHits = 0;
}
}
}
抽象基类有两个派生类——Customer和SiteOwner。这些派生类都实现了基类Contact中的抽象成员。每个派生类中的generateReport()方法声明中都有一个override修饰符。同样,Customer和SiteOwner中的Name属性的声明也都带有override修饰符。当重写方法时,C#有意地要求显式的声明。这种方法可以跳代码的安全性,因为它可以防止意外的方法重写,这在其他语言中确实发生过。省略override修饰符是错误的。同样,添加new修饰符也是错误的。抽象方法必须被重写,不能隐藏。因此既不能使用new修饰符,也不能没有修饰符。
所有抽象类中最出名的就是Object类[译注:.NET Framework中的Object类并不是抽象类]。它可以写作object或Object[译注:object是C#中的关键字,用于声明Object类的一个对象;Object是指.NET Framework类库中的System.Object类],但它们都是同一个类。Object类是C#中所有其他类的基类。它同时也是没有指定基类时的默认基类。下面的这些类声明产生同样的结果:
abstract public class Contact : Object {
// 类成员
}
abstract public class Contact {
// 类成员
}
如果没有声明基类,Object会隐式地成为基类。除了将C#类框架中的所有类联系在一起,Object类还提供了一些内建的功能,这些需要派生类来实现。
接口和抽象类之间的区别
接口和抽象类关系很紧密,它们都具有对成员的抽象。
对于一个抽象类,至少一个方法是抽象方法既可,这意味着它也可以具有具体方法[译注:Concrete Method,这只是相对于抽象方法而言,面向对象中并没有这个概念]。
对于一个接口,所有的方法必须都是抽象的。
实现了一个接口的类必须为接口中的所有方法提供具体的实现,否则只能声明为抽象类。
在C#中,多重继承(Multiple Inheritance)只能通过实现多个接口得到。抽象类只能单继承[译注:C#中的单继承是指所有类作为基类的时候都只能是派生类声明中唯一的基类,而不仅仅是抽象类]。
接口定义的是一个契约,其中只能包含四种实体,即方法、属性、事件和索引器。因此接口不能包含常数(Constant)、域、操作符、构造器、析构器、静态构造器或类型[译注:指嵌套的类型]。
同时,一个接口还不能包含任何类型的静态成员。修饰符abstract、public、protected、internal、private、virtual、override都是不允许出现的,因为它们在这种环境中是没有意义的。
类中实现的接口成员必须具有公有的可访问性。