注意,派生类的构造函数隐式调用了基类(或 Java 术语中的超类)的构造函数。在继承中,所有的基类构造函数都是按照这些类出现在类层次中的顺序在派生类的构造函数之前调用的。
将类型强制转换到基类
与在 Java 中一样,我们不能使用对基类的引用来访问派生类的成员和方法,即使基类引用可能包含对派生类型对象的有效引用也同样如此。
我们可以通过隐式地引用派生的类型来引用派生类:
ColorPoint clrpt = new ColorPoint(); Point pt = clrpt;
在这段代码中,基类引用 pt 包含 clrpt 引用的副本。
base 关键字
通过使用 base 关键字,我们可以访问子类中的基类成员,即使这些基类成员在超类中被重写也同样如此。例如,我们可以创建一个派生类,该类所包含的方法具有与基类中相同的签名。如果我们在此方法前加上 new 关键字,就表示这是一个属于派生类的全新方法。通过 base 关键字,我们仍然可以提供方法来访问基类中的原始方法。
例如,我们的 Point 基类有名为 invert() 的方法,它交换 x 和 y 坐标。通过使用下面这样的代码,我们可以在派生类 ColorPoint 中提供此方法的替代方法:
public new void invert()
{
int holding = X;
X = Y;
Y = holding;
screenColor = Color.Gray;
}
正如您所见,该方法交换 x 和 y,然后将点的颜色设置为灰色。通过在 ColorPoint 中创建另一个方法(例如下面的这个方法),我们可以提供对此方法的基实现的访问:
public void baseInvert()
{
base.invert();
}
然后,我们就可以通过调用 baseInvert() 方法来调用 ColorPoint 对象中的基方法。
ColorPoint clrpt = new ColorPoint();clrpt.baseInvert();
请记住,如果我们将对基类的引用赋值给 ColorPoint 的实例,然后访问它的方法,我们将获得相同的效果:
Point pt = clrpt; pt.invert();
选择构造函数
基类对象总是在任何派生类之前构造的。因此基类的构造函数在派生类的构造函数之前执行。如果基类有多个构造函数,派生类就可以决定要调用的构造函数。例如,我们可以修改我们的 Point 类来添加第二个构造函数:
public class Point
{
private int x, y;
public Point()
{
x = 0; y = 0;
}
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
}
然后,通过使用 base 关键字,我们可以将 ColorPoint 类更改为使用某个特定的可用构造函数:
public class ColorPoint : Point
{
private Color color;
public ColorPoint(int x, int y) : base (x, y)
{
color = Color.Red;
}
}
在 Java 中,这项功能是通过 super 关键字来实现的。
方法重写
通过为声明的方法提供新的实现,派生类可以重写基类的方法。Java 和 C# 之间的一个重要区别在于,Java 方法在默认情况下标记为虚方法,而在 C# 中,必须使用 virtual 修饰符才能将方法显式标记为虚方法。可以采用大致相同的方式重写属性访问器以及方法。
虚方法
派生类中要被重写的方法是用 virtual 修饰符声明的。而在派生类中,已被重写的方法用 override 修饰符声明。
override 修饰符表示派生类的方法或属性,这个派生类代替基类中具有相同的名称和签名的类。要被重写的基方法必须声明为 virtual、abstract 或 override:以这种方式重写非虚方法或静态方法是不可能的 — 请参见关于此问题的下一部分。已被重写的方法或属性和重写方法或属性必须具有相同的访问级修饰符。
下面的示例显示了一个称为 StepUp 的虚方法,它是在派生类中用 override 修饰符重写的:
using System;
public class CountClass
{
public int count;
// Constructor
public CountClass(int startValue)
{
count = startValue;
}
public virtual int StepUp()
{
return count;
}
}
class Count100Class : CountClass
{
// Constructor
public Count100Class(int x) : base(x)
{
}
public override int StepUp()
{
return ((base.count) 100);
}
public static void Main()
{
CountClass counter = new CountClass(10);
CountClass bigCounter = new Count100Class(10);
Console.WriteLine("Value of count in base class = {0}",
counter.StepUp());
Console.WriteLine("Value of count in derived class = {0}",
bigCounter.StepUp());
}
}
当我们运行这段代码时,会发现派生类的构造函数使用基类中给出的方法体,这使得我们在不复制该代码的情况下就可以初始化 count 成员。下面是我们得到的输出结果:
Value of count in base class = 11 Value of count in derived class = 110
抽象类
抽象类将一个(或多个)方法或属性声明为抽象的。这样的方法并不具有声明它们的类中提供的实现,尽管抽象类也可以包含非抽象方法,也就是说,已经为其方法提供了实现。抽象类不能直接实例化,而只能作为派生类。这样的派生类必须为所有的抽象方法和属性提供实现(使用 override 关键字),除非派生成员本身被声明为抽象的。
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!




