然后,我们就可以通过调用 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 关键字),除非派生成员本身被声明为抽象的。
下面的示例声明了一个抽象的 Employee 类。我们还创建了一个名为 Manager 的派生类,它提供了定义在 Employee 类中的抽象方法 show() 的实现:
using System;
public abstract class Employee
{
// abstract show method
public abstract void show();
}
// Manager class extends Employee
public class Manager: Employee
{
string name;
public Manager(string name)
{
this.name = name;
}
//override the show method
public override void show()
{
Console.WriteLine("Name : " + name);
}
}
public class CreateManager
{
public static void Main(string[] args)
{
// Create instance of Manager and assign it to an Employee reference
Employee temp = new Manager("John Chapman");
// Call show method. This will call the show method of the Manager class
temp.show();
}
}
这段代码调用了由 Manager 类提供的 show() 实现,并且在屏幕上打印出雇员的名字。
接口 接口是一种“主干类”,包含方法签名但是没有方法的实现。在这个方面,接口与抽象类一样,只包含抽象方法。C# 接口非常类似于 Java 接口,工作原理基本一样。
接口的所有成员都定义为公共成员,并且接口不能包含常量、字段(私有数据成员)、构造函数、析构函数或任何类型的静态成员。如果为接口的成员指定任何修饰符,编译器将会产生错误。
为了实现接口,我们可以从接口派生类。这样的派生类必须为所有接口的方法提供实现,除非派生类声明为抽象的。
接口的声明与 Java 完全一样。在接口定义中,通过单独使用 get 和 set 关键字,属性仅指示它的类型,以及它是只读的、只写的还是可读写的。下面的接口声明了一个只读属性:
public interface IMethodInterface
{
// method signatures
void MethodA();
int MethodB(float parameter1, bool parameter2);
// properties
int ReadOnlyProperty
{
get;
}
}
用一个冒号来代替 Java 的实现关键字,类就可以继承此接口。实现类必须提供所有方法的定义以及任何必需的属性访问器:
public class InterfaceImplementation : IMethodInterface
{
// fields
private int count = 0;
private int ID;
// implement methods defined in interface
public void MethodA()
{
...
}
public int MethodB(float parameter1, bool parameter2)
{
...
return integerVariable;
}
public int ReadOnlyProperty
{
get
{
return count;
}
}
// add extra methods if required
}
实现多个接口
通过使用下面的语法,一个类可以实现多个接口:
public class MyClass : interfacename1, interfacename2, interfacename3
如果一个类实现多个接口,则成员的名称会存在二义性,通过使用属性或方法名的完全限定符可以解决这个问题。换句话说,通过使用方法的完全限定名来指示它属于哪个接口(例如属于 IMethodInterface.MethodA),派生类可以解决这种冲突。
运算符重载 与 C++ 一样,C# 允许我们重载运算符,以供在我们自己的类中使用。这可能使得用户定义的数据类型看起来很自然,并且可以在逻辑上作为基本数据类型使用。例如,我们可以创建一个新的名为 Complex 的数据类型来表示一个复杂的数字,并且提供一些方法,以使用标准的算术运算符对这样的数字进行算术运算,例如使用 + 运算符来使两个复杂的数字相加。
为了重载一个运算符,我们编写了一个函数,它将需要重载的运算符的符号放在名称 operator 的后面。例如,我们可以这样来重载 + 运算符:
public static complex operator+(complex lhs, complex rhs)
所有的运算符重载都是类的静态方法。同时也需要注意,如果您重载等于运算符 (==),您还必须重载不等于运算符 (!=)。
可以重载的运算符的完整列表如下:
一元运算符: +, -, !, ~, ++, --, true, false
二元运算符: +, -, *, /, %, &, |, ^, <<, >>, ==, !=, >, <, >=, <=
下一个示例创建了一个 Complex 类,该类重载 + 和 - 运算符:
using System;
public class complex
{
private float real;
private float img;
<