抽象类与接口
1.抽象类
举个例子:去书店买书。这句话描述的就是一个抽象行为,但底是去哪家书店,买什么数。“去书店买书”这句话中,并没有买书行为必须包含的确定信息,如果将去书店买书这个动作封装为一个行为类,那么这个类就应该是一个抽象类。
注:1.C#中规定,类中只要有一个方法声明为抽象方法,这个类也必须声明为抽象类。
2.抽象类中不一定所有方法都是抽象方法或抽象属性。
抽象类具有以下特性:
l 抽象类不能被实例化。
l 抽象类可以包含抽象方法和抽象的访问器。
l 不能用sealed修饰符修饰该抽象类,这意味着抽象类不能被继承。
l 从抽象类派生的非抽象类,必须包括继承的所有抽象方法和抽象访问器的实现。
l 在方法或属性声明中用abstract修饰符,以指示方法或属性为抽象方法或抽象属性。
抽象方法具有下列特性:
l 抽象方法是隐式的虚方法(virtual),所以在实现抽象方法或抽象属性时需要用override来修饰实现方法或实现属性。
l 只允许在抽象类中使用抽象方法声明。
l 因为抽象方法声明不提供实际的实现,所以没有方法体。方法声明是以一个分号结束,并且在签名后没有大括号{}。
l 实现由一个重载方法提供,此重载方法是非抽象类的成员。
l 在抽象方法声明中使用static或virtual修饰符是错误的。
l 抽象属性必须写访问器。
l 如果继承了某个抽象类,那么就要实现抽象类里面所有的抽象方法和属性(除非继承类也是抽象类)。
注:如果一个没有用Abstract修饰的类继承了一个抽象类,但是并没有全部实现抽象类里面所有的抽象方法和属性,那么这个类就会被默认为抽象类(尽管没有用Abstract修饰)。
在设计和声明一个抽象类时,注意:不要在抽象类中定义公共或内部受保护的构造函数。如果需要构造函数,应该在抽象类中声明为受保护的或内部构造函数。应该至少提供一个该抽象类的具体实现。
定义了抽象方法或抽象属性,那么在继承类中就必须为抽象类
//定义一个抽象类
public abstract class Shape
{
public abstract float area();
public abstract string Why//抽象属性必须写访问器,不然会报错,不能实现抽象属性。
{
get;
set;
}
public void pring()
{
Console.WriteLine(Why);
}
}
//继承抽象类,并实现抽象里面所有的抽象方法和属性。
public class Rectangle : Shape
{
private int length;
private int width;
private string why;
public override string Why
{
get
{
return why;
}
set
{
why = value;
}
}
public Rectangle(int length, int width) //构造器
{
this.length = length;
this.width = width;
}
public override float area() //计算面积
{
return (float)(length * width);
}
public void showArea()
{
Console.WriteLine(Why);
Console.WriteLine("正方形面积为:" + area() + "\n");
}
}
//主类
class Program
{
static void
{
Rectangle rectangle = new Rectangle(1, 2);
rectangle.Why = "这是什么啊?";
rectangle.showArea();
Console.Read();
}
}
2.接口
接口提供了一种契约,让使用接口的用户必须严格遵守接口提供的约定。
接口具有下列属性:
l 接口类类似于抽象类,继承接口的然后非抽象类型都必须实现接口的所有成员。
l 不能直接实例化接口。
l 接口可以包含事件、索引器、方法和属性。
l 接口不包含方法的实现,而抽象类可以包含方法的实现。
l 类和结构可以多个接口继承。
l 接口自身也可以从多个接口继承。
l 接口的成员必须是方法、属性、事件或索引器。
l 接口不能包含常量、字段、运算符、实例构造函数、析构函数或类型,也不能包含任何种类的静态成员。
l 接口成员声明包含任何修饰符都十余编译时错误。集体来说就是不能用任何修饰符来修饰接口中的成员。
l 所有接口成员都隐式地具有public访问属性。
l 关键字Abstract和sealed,virtual,static不能在接口中使用,因为这两个修饰符在接口定义中是没有意义的(它们不包含执行代码,所以不能直接实例化,且必须是可以继承的)
注:在定义接口中不能用virtual ,Abstract,sealed关键字来修饰接口中的属性或方法,但是可以在实现接口的类中使用。在实现接口的类中使用virtual的作用就在于将该类为基类时,子类对实现重写(父类实现了接口,子类自然拥有接口中的方法,而通过重载父类中的方法来表现自己的方法)
接口不能单独存在,不能像实例化一个类那样实例化接口。
如:
public interface Shap
{
float area(); 接口中不能用关键字virtual来修饰。