5 抽象类和封闭类
(1)封闭类又称最终类,他的特点简单:不能被继承.要用sealed 修饰成为封闭类的类似通常是些不宜改动的.
(2)抽象方法,属性,索引器
抽象方法格式:abstract 返回类型 方法名(参数列表);
抽象属性格式:abstrct 返回类型 属性名{get;set;}
索引器格式:abstrart 返回类型 this[参数列表]{get;set;}
(3)抽象类格式:
abstract class 类名{....}
虽然抽象类不能产生对象,但是抽象类完全可以有构造函数.
抽象类是被继承,所以不能和sealed联用.
抽象类的派生类可以是抽象类,只有当派生类实现了所有抽象成员后,才演化为一个普通的类,这熟才能产生对象.
6 多态
(1)虚成员
关键字virtual修饰的成员陈为虚方法.虚成员有虚方法,虚属性,虚索引器.
(2)重写
重写又是覆盖,需要关键字override.如果重写基类的virtual成员,派生类的同名成员没有用 override就等于是默认了new关键字,就产生了一个新的成员,并且隐藏了(而不是重写了)基类的同名的虚成员.
(3)多态
用基类类名声名,但是用派生类构造函数创建.
(4)上溯
把派生类的对象当作基类的对象来处理,陈之为上溯.
程序3
using System;
using System.Collections.Generic;
using System.Text;
namespace school
{
class A
{
public void Func() //基类A非虚方法
{
Console.WriteLine("Func()in A");
}
public virtual void VO() //基类A虚方法
{
Console.WriteLine("BaseClass.VO()");
}
}
class B : A
{
public int j;
new public void Func() //派生类B隐藏基类非虚方法
{
j = 2;
Console.WriteLine("Func()inB,the new member="+j);
}
public override void VO() // 派生类B重写基类虚方法
{
j = 2;
Console.WriteLine("VO()inB,the new member="+j);
}
public void FromBase() //派生类B调用基类虚方法
{
base.VO();
}
}
class C:B
{
public int k;
new public void Func() //派生类C隐藏基类非虚方法
{
k = 3;
Console.WriteLine("Func()inC,the new member=" + k);
}
public override void VO() //派生类C重写基类虚方法
{
k = 3;
Console.WriteLine("VO()in C,the new member="+k);
}
}
class D : C
{
public int m;
new public void Func() //派生类D隐藏基类非虚方法
{
m = 4;
Console.WriteLine("Func()in D,the new member="+m);
}
new public virtual void VO() //派生类D隐藏基类虚方法
{
m = 4;
Console.WriteLine("Func()in D,the new member=" + m);
}
}
class E : D
{
public int n;
new public void Func() //派生类E隐藏基类虚方法
{
n = 5;
Console.WriteLine("Func()in E,the new member="+n);
}
public override void VO() //派生类E重写基类虚方法
{
n = 5;
Console.WriteLine("VO()in E,the new member="+n);
}
}
class Test
{
public static void VirtualandOverride(A a)
{
a.Func();
a.VO();
}
public static void Main()
{
A aa = new A(); //基类对象 aa
A ab = new B(); //或者A ab=bb;用基类名声明,用派生类构造函数
B bb = new B(); //派生类对象bb
ab.Func(); //调用非虚方法,输出:“Func()in A”
bb.Func(); // 调用非虚方法,Func()in B,the new member=2
aa.VO(); // 输出:“baseclass.VO()”
// Console .WriteLine("ab.j"); //错误:A中并不包含对J的定义。ab的类型是A?
ab.VO(); //调用虚方法,输出:"VO()in B,the new member=2"
bb.VO(); // 调用虚方法,输出:"VO()in B,the new member=2"
bb.FromBase (); //输出:"BaseClass.VO()"
Console .WriteLine ("ab.Totring()"); //输出:"B".ab的类型是B?
Console .WriteLine ("Testing");
VirtualandOverride (aa);
VirtualandOverride(ab);
A ac=new C();
VirtualandOverride(ab);
A ae=new E();
VirtualandOverride(ae);
}
}
}
程序3的输出如下:
Func()in A
Func()in B,the new member=2
BaseClass.VO()
VO()in B,the new member=2
VO()in B,the new member=2
BaseClass.VO()
B
Testing
Func()in A
BaseClass.VO()
Func()in A
VO()in B,the new member=2
Func()in A
VO()in C,the new member=3
Func()in A
VO()in C,the new member=3
Func()in A
VO()in C,the new member=3
Test类中首先定义了测试方法VirtualandOverride,其作用是依次调用一个对象的非虚方法Func()和虚方法vo().
在Main方法中首先创建了基类对象aa,派生类B的对象bb,还用基类A生命,用派生类B构造函数创建的多态对象ab.
ab.Func();通过多态对象调用非虚方法(),调用A中定义的Func(),还是调用B中定义的Func,取决于ab的类型,ab是用A声明的,所以调用A中的Func类型.
B ba;
ba=aa; //错误:无法将类型"A"隐式转换为"B"
ba=ab; //错误:无法将类型"A"隐式转换为"B"
ba=(B)aa; //编译通过,执行中错误
ba=(B)ab; //正确
aa=ab; //正确
ab=aa; //正确
可以看出,通过多态对象的形式,基类对象使用了派生类的方法;这样,基类在不用改变方法代码的条件下,改进或扩张了自身的功能.
Console .WriteLine ("ab.Totring()"); Object.Tostring()方法是虚方法,在调用虚方法时,系统回把多态看成是派生类的事例.
Func()是非虚方法,程序按声明的内容执行.VO()方法是重写方法,是按照运行中的实际对象决定调用哪个类中的方法.多态对象调用虚方法时或虚方法重写时,调用的是重写方法.多态对象ac调用Func()和VO()方法,ac中VO是重写的方法,override后的方法是可以再次被派生类使用,当一个派生类被多次重写时,决定究竟是哪个方法被调用是由上溯决定的,这里由A到B,由B到C,调用C中的重写方法.
在D定义中VO并没有使用override,而是使用Virtual new,这样D中的VO就隐藏了积累中的VO方法,如果有以下:
D dd=new D();
dd.VO();输出为:VO()in D,the new member=4
如果ae改为以下:D ae=new E();
de.vo()输出为:VO() in E,the new member=5
7 结构和类的比较
结构是值类型,结构对象存放在栈中;类是引用类型.类的对象存放在堆中.
参考书<<Visual c#.NET程序设计教程>>
转载于:https://www.cnblogs.com/chjun2000/archive/2009/12/21/1629234.html