继承的类型
在面向对象的编程中,有两种截然不同的继承类型:实现继承和接口继承。
实现继承:表示一个类型派生于一个基类型,它拥有该基类型的所有成员字段和函数。在
实现继承中,派生类型采用基类型的每个函数的实现代码,除非在派生类型的定义中指定
重写某个函数的实现代码。在需要给现有的类型添加功能,或许多相关的类型共享一组重
要的公共功能时,这种类型的继承非常有用。
接口继承:表示一个类型只继承了函数的签名,没有继承任何实现代码。在需要指定该类
型具有某些可用的特性时,最好使用这种类型的继承。
C#支持实现继承和接口继承。它们都内置于语言和架构中,因此可以根据应用程序的体系结构
选择合适的继承。
实现继承
如果要声明派生自另一个类的一个类,就可以使用下面的语法:
class MyDerivedClass: MyBaseclass
{
// functions and data members here
}
如果类(或结构)也派生自接口,则用逗号分隔列表中的基类和接口:
public class MyDerivedClass: MyBaseC1ass` IInterface1、 IInterface2
{
// etc.
}
对于结构,语法如下:
public struct MyDeriVedstruct: IInterface1、 IInterface2
{
// etc.
}
虚方法
把一个基类函数声明为virtual,就可以在任何派生类中重写该函数:
class MyBaseClass
{
public virtual string Virtua1Method()
{
return "This method is virtual and defined in MyBaseC1ass";
}
}
也可以把属性声明为△i血剧。对于虚属性或重写属性,语法与非虚属性相同,但要在定义中添
加关键字virtual,其语法如下所示:
public virtua△ string ForeName
{
get {returh foreName;}
set { foreName =Value;}
}
C#中虚函数的概念与标准00P的概念相同:可以在派生类中重写虚函数。在调用方法时,会调用该类对象的合适方法。
在C#中,函数在默认情况下不是虚拟的,但(除了构造函数以外)可以显
式地声明为virual。这遵循C++的方式,即从性能的角度来看,除非显式指定,否则函数就不是虚
拟的。而在Java中,所有的函数都是虚拟的。但C#的语法与C++的语法不同,因为C#要求在派生
类的函数重写另一个函数时,要使用override关键字显式声明。
重写方法的语法避免了C++中很容易发生的潜在运行错误:当派生类的方法签名无意中与基类
版本略有差别时,该方法就不能重写基类的方法:在C#中,这会出现一个编译错误,因为编译器会
认为函数已标记为override,但没有重写其基类的方法。
成员字段和静态函数都不能声明为virual,因为这个概念只对类中的实例函数成员有意义。
隐藏方法
如果签名相同的方法在基类和派生类中都进行了声明,但该方法没有分别声明为virual和
override,派生类方法就会隐藏基类方法。
在大多数清况下,是要重写方法,而不是隐藏方法,因为隐藏方法会造成对于给定类的实例调用
错误方法的危险。
调用函数的基类版本
C#有一种特殊的语法用于从派生类中调用方法的基类版本:base.<MethodName>()。
抽象类和抽象函数
C#允许把类和函数声明为abstract。抽象类不能实例化,而抽象函数不能直接实现,必须在非抽
象的派生类中重写。显然,抽象函数本身也是虚拟的(尽管也不需要提供virual关键字,实际上,如
果提供了该关键字,就会产生一个语法错误。如果类包含抽象函数,则该类也是抽象的,也必须声
明为抽象的:
abstract class Building
{
pvblic abstract decimal CalCulateHeatingCost(); // abstract method
}
密封类和密封方法
C#允许把类和方法声明为sealed。对于类,这表示不能继承该类:对于方法,这表示不能重写
该方法。
sealed c1ass FinalClass
{
// etc
}
class DerivedClass: FinalClass // wrong. Wi1l give compilation error
{
// etc
}
在把类或方法标记为sealed时,最可能的情形是:如果要对库、类或自己编写的其他类作用域
之外的类或方法进行操作,则重写某些功能会导致代码混乱。也可以因商业原因把类或方法标记为sealed,以防第三方以违反授权协议的方式扩展该类。但一般情况下,在把类或成员标记为sealed时要小心,因为这么做会严重限制它的使用方式。即使认为它不能对继承自一个类或重写类的某个成员发挥作用,仍有可能在将来的某个时刻,有人会遇到我们没有预料到的情形,此时这么做就很有用。.NET基类库大量使用了密封类,使希望从这些类中派生出自己的类的第三方开发人员无法访问这些类。例如,string就是一个密封类。
可见性修饰符
在面向对象的编程中,有两种截然不同的继承类型:实现继承和接口继承。
实现继承:表示一个类型派生于一个基类型,它拥有该基类型的所有成员字段和函数。在
实现继承中,派生类型采用基类型的每个函数的实现代码,除非在派生类型的定义中指定
重写某个函数的实现代码。在需要给现有的类型添加功能,或许多相关的类型共享一组重
要的公共功能时,这种类型的继承非常有用。
接口继承:表示一个类型只继承了函数的签名,没有继承任何实现代码。在需要指定该类
型具有某些可用的特性时,最好使用这种类型的继承。
C#支持实现继承和接口继承。它们都内置于语言和架构中,因此可以根据应用程序的体系结构
选择合适的继承。
实现继承
如果要声明派生自另一个类的一个类,就可以使用下面的语法:
class MyDerivedClass: MyBaseclass
{
// functions and data members here
}
如果类(或结构)也派生自接口,则用逗号分隔列表中的基类和接口:
public class MyDerivedClass: MyBaseC1ass` IInterface1、 IInterface2
{
// etc.
}
对于结构,语法如下:
public struct MyDeriVedstruct: IInterface1、 IInterface2
{
// etc.
}
虚方法
把一个基类函数声明为virtual,就可以在任何派生类中重写该函数:
class MyBaseClass
{
public virtual string Virtua1Method()
{
return "This method is virtual and defined in MyBaseC1ass";
}
}
也可以把属性声明为△i血剧。对于虚属性或重写属性,语法与非虚属性相同,但要在定义中添
加关键字virtual,其语法如下所示:
public virtua△ string ForeName
{
get {returh foreName;}
set { foreName =Value;}
}
C#中虚函数的概念与标准00P的概念相同:可以在派生类中重写虚函数。在调用方法时,会调用该类对象的合适方法。
在C#中,函数在默认情况下不是虚拟的,但(除了构造函数以外)可以显
式地声明为virual。这遵循C++的方式,即从性能的角度来看,除非显式指定,否则函数就不是虚
拟的。而在Java中,所有的函数都是虚拟的。但C#的语法与C++的语法不同,因为C#要求在派生
类的函数重写另一个函数时,要使用override关键字显式声明。
重写方法的语法避免了C++中很容易发生的潜在运行错误:当派生类的方法签名无意中与基类
版本略有差别时,该方法就不能重写基类的方法:在C#中,这会出现一个编译错误,因为编译器会
认为函数已标记为override,但没有重写其基类的方法。
成员字段和静态函数都不能声明为virual,因为这个概念只对类中的实例函数成员有意义。
隐藏方法
如果签名相同的方法在基类和派生类中都进行了声明,但该方法没有分别声明为virual和
override,派生类方法就会隐藏基类方法。
在大多数清况下,是要重写方法,而不是隐藏方法,因为隐藏方法会造成对于给定类的实例调用
错误方法的危险。
调用函数的基类版本
C#有一种特殊的语法用于从派生类中调用方法的基类版本:base.<MethodName>()。
抽象类和抽象函数
C#允许把类和函数声明为abstract。抽象类不能实例化,而抽象函数不能直接实现,必须在非抽
象的派生类中重写。显然,抽象函数本身也是虚拟的(尽管也不需要提供virual关键字,实际上,如
果提供了该关键字,就会产生一个语法错误。如果类包含抽象函数,则该类也是抽象的,也必须声
明为抽象的:
abstract class Building
{
pvblic abstract decimal CalCulateHeatingCost(); // abstract method
}
密封类和密封方法
C#允许把类和方法声明为sealed。对于类,这表示不能继承该类:对于方法,这表示不能重写
该方法。
sealed c1ass FinalClass
{
// etc
}
class DerivedClass: FinalClass // wrong. Wi1l give compilation error
{
// etc
}
在把类或方法标记为sealed时,最可能的情形是:如果要对库、类或自己编写的其他类作用域
之外的类或方法进行操作,则重写某些功能会导致代码混乱。也可以因商业原因把类或方法标记为sealed,以防第三方以违反授权协议的方式扩展该类。但一般情况下,在把类或成员标记为sealed时要小心,因为这么做会严重限制它的使用方式。即使认为它不能对继承自一个类或重写类的某个成员发挥作用,仍有可能在将来的某个时刻,有人会遇到我们没有预料到的情形,此时这么做就很有用。.NET基类库大量使用了密封类,使希望从这些类中派生出自己的类的第三方开发人员无法访问这些类。例如,string就是一个密封类。
可见性修饰符