C# 抽象类与抽象方法.doc
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
C# 抽象类与抽象方法
朋友曾问我抽象类是否至少要有一个抽象方法,我查了很多资料,结果都是:“抽象类允许(但不要求)抽象类包含抽象成员”。
但是一个抽象类里不写抽象方法就没有意义了,既然如此,还不如直接写个普通类?在一个抽象类里可以不声明抽象方法,这在语法上是没问题的,但实际来说,这样是没有任何意义的。
也就是说,你为什么会选择写一个抽象类呢?当然是为了想某个方法能够被OVERRIDE,以实现多态。
后来查找MSDN结果如下:
abstract 修饰符可以和类、方法、属性、索引器及事件一起使用。
在类声明中使用abstract修饰符以指示类只能是其他类的基类。
抽象类具有以下特性:
o抽象类不能实例化。
o抽象类可以包含抽象方法和抽象访问器。
o不能用sealed修饰符修改抽象类,这意味着该类不能被
继承。
o从抽象类派生的非抽象类必须包括继承的所有抽象方法
和抽象访问器的实实现。
在方法或属性声明中使用abstract修饰符以指示此方法或属性不包含实现。
抽象方法具有以下特性:
o抽象方法是隐式的virtual方法。
o只允许在抽象类中使用抽象方法声明。
o因为抽象方法声明不提供实实现,所以没有方法体;方法
声明只是以一个分号结束,并且在签名后没有大括号
({ })。
例如:
public abstract void MyMethod();
o实现由overriding 方法提供,它是非抽象类的成员。
o在抽象方法声明中使用static或virtual修饰符是错
误的。
除了在声明和调用语法上不同外,抽象属性的行为与抽象方法一样。
o在静态属性上使用abstract修饰符是错误的。
o在派生类中,通过包括使用override修饰符的属性声
明可以重写抽象的继承属性。
抽象类必须为所有接口成员提供实现。
MSDN中C#语言规范的:10.1.1.1抽象类。
此文如下:
abstract修饰符用于表示所修饰的类是不完整的,并且它只能用作基类。
抽象类与非抽象类在以下方面是不同的:
o抽象类不能直接实例化,并且对抽象类使用new运算符
是编译时错误。
虽然一些变量和值在编译时的类型可以
是抽象的,但是这样的变量和值必须或者为null,或
者含有对非抽象类的实例的引用(此非抽象类是从抽象
类派生的)。
o允许(但不要求)抽象类包含抽象成员。
o抽象类不能被密封。
当从抽象类派生非抽象类时,这些非抽象类必须具体实现所继承的所有抽象成员,从而重写那些抽象成员。
在下面的示例中
1abstract class A
2{
3public abstract void F();
4}
5abstract class B: A
6{
7public void G() {}
8}
9class C: B
10{
11public override void F() {
12// actual implementation of F
13}
14}
抽象类A引入抽象方法F。
类B引入另一个方法G,但由于它不提供F的实现,B也必须声明为抽象类。
类C重写F,并提供一个具体实现。
由于C中没有了抽象成员,因此可以(但并非必须)将C声明为非抽象类。
有关抽象类和抽象方法的问题,我个人也做了一些总结,如下:
§ abstract关键字用于将类指定为抽象类,这些抽象类可以派生出其他类。
a.一个抽象类可以同时包含抽象方法和非抽象方法。
b.抽象方法的目的在于指定派生类必须实现与这一
方法关联的行为。
c.抽象方法只在派生类中真正实现,这表明抽象方法
只存放函数原型(方法的返回类型,使用的名称及
参数),而不涉及主体代码。
d.如果父类被声明为抽象类,并存在未实现的抽象方
法,那么子类就必须实现父类中所有的abstract成
员,除非该类也是抽象的。
例如:
1abstract class A
2{
3public abstract void F();
4}
5
6abstract class B: A
7{
8public void G()
9 {}
10}
11
12class C: B
13{
14public override void F()
15 {
16// actual implementation of F
17 }
18}
19
20
说明:抽象类A引入抽象方法F。
类B引入另一个方法G,但由于它不提供F的实现,B也必须声明为抽象类。
类C重写F,并提供一个具体实现。
由于C中没有了抽象成员,因此可以(但并非必须)将C声明为非抽象类。
e.抽象类不能被实例化,使用override关键字可在派
生类中实现抽象方法,经override声明重写的方法,
其签名必须与override方法的签名一致。
C#.NET 虚方法中中的virtual 和override关键字的使用收藏
谈到C#.NET的虚方法就不得不先说一下继承性(inheritance),继承和多态度、封装一起构成面向对象程序设计的三大要素,继承指一个类基于一个已有的类按照需求添加和删除一些功能.
首先,我们通过下面一个例子来了解一下virtual 和override关键字的作用.
class CA
{
public void Foo()
{
Console.WriteLine("CA.Foo");
}
}
class CB : CA
{
public void Foo()
{
Console.WriteLine("CB.Foo");
}
}
class Test
{
public static void InvokeFoo(CA ca)
{
ca.Foo();
}
public static void Main()
{
InvokeFoo(new CB());
}
}
我们先试着猜想一下输出的结果应该为什么,从逻辑上说作者想要得到的应该是输出:CB.Foo.但我们执行一次很容易的发现结果是CA.Foo.这是怎么回事呢.我们的CB类不是已经继承了CA类吗,而我们的InvokeFoo方法不是也已经创建了一个新的CB对象吗?怎么最后的结果却是CA.Foo.
因为在调用InvokeFoo()的时候,CB被转换成CA,所以执行ca.Foo的时候,仍然调用的是CA的Foo。
那怎样才能让这段代码按作者的意图输出CB.Foo了?我们再来看看下面的这段代码,注意它与上面代码的不同之处:
class CA
{
public virtual void Foo()
{
Console.WriteLine("CA.Foo");
}
}
class CB : CA
{
public override void Foo()
{
Console.WriteLine("CB.Foo");
}
}
class Test
{
public static void InvokeFoo(CA ca)
{
ca.Foo();
}
public static void Main()
{
InvokeFoo(new CB());
}
}
输出结果:CB.Foo
可能大家已经注意到了,我们在基类CA的Foo()方法前使用了virtual关键字体,在子类CB的Foo()方法前使用了override关键字.恰恰就是这两个关键字帮助我们实现了我们的想法.那他们究竟又做了些什么呢?原来virtual关键字告诉编译器,当前Foo()方法需要运行时才进行绑定,而override关键字告诉编译器它后面的Foo()方法将要覆盖基类中的Foo()方法.因此尽管在调用InvokeFoo()的时候,CB被转换成CA,但是当执行ca.Foo的时候,仍然调用了CB的Foo。
因为ca此时指向的是一个CB类型的对象
本文来自CSDN博客,转载请标明出处:/princelele/archive/2008/10/07/3027260.aspx。