C#中Abstract 、Virtual和Override的使用
1. abstract 修饰符指示所修饰的内容缺少实现或未完全实现。 abstract 修饰符可用于类、方法、属性、索引器和事件。在类声明中使用abstract修饰符以指示某个类只能是其他类的基类。标记为抽象或包含在抽象类中的成员必须通过从抽象类派生的类来实现。
(1)抽象类具有以下特性:
1) 抽象类不能实例化。
2) 抽象类可以包含抽象方法和抽象访问器。
3) 不能用 sealed 修饰符修饰抽象类,因为这两个修饰符的含义是相反的。采用 sealed 修饰符的类无法继承,而 abstract 修饰符要求对类进行继承。
4) 从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实际实现。
5) 在方法或属性声明中使用 abstract 修饰符以指示方法或属性不包含实现。
(2)抽象方法具有以下特性:
1) 抽象方法是隐式的虚方法。
2) 只允许在抽象类中使用抽象方法声明。
3) 因为抽象方法声明不提供实际的实现,所以没有方法体;方法声明只是以一个分号结束,并且在签名后没有大括号 ({ })。
(3)在抽象方法声明中使用 static 或 virtual 修饰符是错误的。除了在声明和调用语法上不同外,抽象属性的行为与抽象方法一样。在静态属性上使用abstract修饰符是错误的。在派生类中,通过包括使用 override 修饰符的属性声明,可以重写抽象的继承属性。
public abstract class parent
{
protected int x=100;
protected int y = 200;
public abstract void function();
public abstract int X { get; }
public abstract int Y { get; }
}
public class newperson : parent
{
public override void function()
{
x++;
y++;
}
public override int X
{
get { return x+100; }
}
public override int Y
{
get { return y+100; }
}
}
static void Main(string[] args)
{
newperson p = new newperson();
Console.WriteLine(p.X);
Console.WriteLine(p.Y);
p.function();
Console.WriteLine(p.X);
Console.WriteLine(p.Y);
Console.ReadKey();
}
2. virtual关键字用于修饰方法、属性、索引器或事件声明,并使它们可以在派生类中被重写。虚拟成员的实现可由派生类中的重写成员更改。调用虚方法时,将为重写成员检查该对象的运行时类型。将调用大部分派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员。默认情况下,方法是非虚拟的。不能重写非虚方法。virtual 修饰符不能与 static、abstract, private 或 override 修饰符一起使用。和抽象方法的相同点是都用了override关键字进行重写方法,不同点是抽象方法必须存在于抽象类中,而子类必须重写,除非子类也是抽象的。
public class Dimensions
{
public const double PI = Math.PI;
protected double x;
protected double y;
public Dimensions() { }
public Dimensions(double x, double y)
{
this.x = x;
this.y = y;
}
public virtual double Area()
{
return x * y;
}
}
public class Circle : Dimensions
{
public Circle(double r) : base(r,0) { }
public override double Area()
{
Console.WriteLine(base.Area());
return PI * x * x;
}
}
public class Sphere : Dimensions
{
public Sphere(double r) : base(r,0) { }
public override double Area()
{
return 4 * PI * x * x;
}
}
public class Cylinder : Dimensions
{
public Cylinder(double r, double h) : base(r, h) { }
public override double Area()
{
return 2 * PI * x * x + 2 * PI * x * y;
}
}
static void Main(string[] args)
{
Dimensions P = new Circle(5.0);
Sphere sphere = new Sphere(10);
Cylinder cylinder = new Cylinder(10, 10);
Console.WriteLine(P.Area());
Console.WriteLine(sphere.Area());
Console.WriteLine(cylinder.Area());
Console.ReadKey();
}
3.override 方法提供从基类继承的成员的新实现。由 override 声明重写的方法称为重写基方法。重写的基方法必须与 override 方法具有相同的签名。不能重写非虚方法或静态方法。重写的基方法必须是 virtual、abstract 或 override 的。 override 声明不能更改 virtual 方法的可访问性。 override 方法和 virtual 方法必须具有相同的访问级别修饰符。重写属性声明必须指定与继承属性完全相同的访问修饰符、类型和名称,并且被重写的属性必须是 virtual、abstract 或 override 的。
4. base和this的区别
1)base作用:用于从派生类中访问基类的成员,调用基类上已被其他方法重写的方法。指定创建派生类实例时应调用的基类构造函数。
注:从静态方法中使用 base 关键字是错误的。
2)区别:
base 是子类中引用父类,用于在派生类中访问重写的基类成员。
this 是当前类,引用自己,用于访问本类的成员,当然也包括继承而来公有和保护成员。
3)注意:
a).在静态成员中使用base和this都是不允许的。原因是,base和this访问的都是类的实例,也就是对象,而静态成员只能由类来访问,不能由对象来访问。
b).base是为了实现多态而设计的。
c).使用this或base关键字只能指定一个构造函数,也就是说不可同时将this和base作用在一个构造函数上。
d).除了base,访问基类成员的另外一种方式是:显示的类型转换来实现。只是该方法不能为静态方法。