本系列的第二篇主要针对类的继承
- C#中只允许从一个基类派生,而C++可以从多个基类派生;而且C#的继承永远是public的,C++的继承可以是public/private/protected中的一种。
- C#的子类自动包含了父类的所有field,子类的构造函数必须调用基类的构造函数,子类使用base关键字来显式调用基类构造函数;如果你没有显式调用基类构造函数,编译器会试图隐式调用基类的缺省构造函数;如果基类没有一个public的缺省构造函数,子类就必须显式调用基类某个构造函数
class IdentifierToken : Token
{
public IdentifierToken(string name)
: base(name) // calls Token(name)
{
...
}
...
}
- 可以将基类的变量赋值成子类,但是这时只能访问基类中定义的method和field。
IdentierToken it = new IdentifierToken();
Token t = it; // legal as Token is a base class of IdentifierToken
- 如果基类和子类定义了具有相同签名(相同的方法名、同样数量和类型的参数)的方法,子类中的方法会屏蔽基类的方法,如果你确定要这样做且不希望受到编译器的警告,可以使用new关键字
class Token
{
...
public string Name() { ... }
}
class IdentifierToken : Token
{
...
new public string Name() { ... }
}
- C#中可以通过virtual方法来实现多态性,在基类中使用virtual修饰函数,在子类中使用override来定义重新实现;virtual不可以和private共存,子类override的函数自动是virtual的,但是不能使用virtual关键字;子类和基类的两个函数必须具有相同的访问权限。
class Mammal
{
...
public virtual string GetTypeName()
{
return "This is a mammal";
}
}
class Horse : Mammal
{
...
public override string GetTypeName()
{
return "This is a horse";
}
}
class Whale : Mammal
{
...
public override string GetTypeName ()
{
return "This is a whale";
}
}
class Kangaroo : Mammal
{
...
}
Mammal m;
Horse h = new Horse();
Whale w = new Whale();
Kangaroo k = new Kangaroo();
m = h;
Console.WriteLine(m.GetTypeName()); // This is a horse.
m = w;
Console.WriteLine(m.GetTypeName()); // This is a whale.
m = k;
Console.WriteLine(m.GetTypeName()); // This is a mammal.
- Interface可以将方法的名称和实现完全切分,Interface只包含方法的名称、返回值、参数,不包含实现,不包含public等访问修饰符(所有方法缺省都是public的);Interface中不能包含field,即使是static的也不行;Interface不能包含析构函数;Interface内不能嵌套类型(enum, struct, class, interface, delegate);Interface不能从struct/class继承。
interface IComparable
{
int CompareTo(object obj);
}
- 要实现一个Interface,你声明一个class或者struct继承这个Interface,并在其中实现所有的接口方法;
- 在实现接口的时候,如果使用了interface名称限定,称为explicit interface implementation,这种情况下不能使用public等修饰,自动拥有public属性,同时这种情况下方法不能作为virtual方法;如果一个类继承的多个接口中有相同的方法,只能使用这种方法实现,同时在调用的时候也只能通过interface调用;
interface IToken
{
string Name();
}
class Token : IToken
{
...
string IToken.Name()
{
...
}
}
- C#中的类可以同时继承基类和接口,但是基类必须位于继承列表中的第一个,后面可以跟多个interface;Interface不能继承class,但是可以继承interface。
interface IToken
{
...
}
class DefaultTokenImpl
{
...
}
class IdentifierToken : DefaultTokenImpl , IToken
{
...
}
- 你可以使用一个interface变量来引用实现了这个接口的类,但这时你只能调用这个interface中可见的方法。
IdentifierToken it = new IdentifierToken();
IToken iTok = it; // legal
- 抽象类是不可以实例化的类,只能作为其他类的基类,使用abstract关键字修饰。
- C#允许使用sealed关键字修饰类,这种类不能被继承,这种类中不能包含任何virtual方法;Struct全都是sealed的,不可被继承;sealed关键字也可以用于修饰单独的方法,表示这个方法不能被派生类override,你只能对override的方法使用sealed关键字。