C#继承与多态

上传人:微*** 文档编号:171400590 上传时间:2022-11-26 格式:DOCX 页数:51 大小:43.98KB
收藏 版权申诉 举报 下载
C#继承与多态_第1页
第1页 / 共51页
C#继承与多态_第2页
第2页 / 共51页
C#继承与多态_第3页
第3页 / 共51页
资源描述:

《C#继承与多态》由会员分享,可在线阅读,更多相关《C#继承与多态(51页珍藏版)》请在装配图网上搜索。

1、C#继承与多态C#继承与多态、继承的基础知识为了提高软件模块的可复用性和可扩充性,以便提高软件的开发效率,我们总是希望能够利用前人或自己以前的开发成果,同时又希望在自己的开发过程中能够有足够的灵活性,不拘泥于复用的模块。C#这种完全面向对象的程序设计语言提供了两个重要的特性一继承性 inheritance 和多态性 polymorphism。继承是面向对象程序设计的主要特征之一,它可以让您重用代码,可以节省程序设计的时间。继承就是在类之间建立一种相交关系,使得新定义的派生类的实例可以继承已有的基类的特征和能力,而且可以加入新的特性或者是修改已有的特性建立起类的新层次。现实世界中的许多实体之间不

2、是相互孤立的,它们往往具有共同的特征也存在内在的差别。人们可以采用层次结构来描述这些实体之间的相似之处和不同之处。图1类图上图反映了交通工具类的派生关系。最高层的实体往往具有最般最普遍的特征,越下层的事物越具体,并且下层包含了上层的特征。它们之间的关系是基类与派生类之间的关系。为了用软件语言对现实世界中的层次结构进行模型化,面向对象的程序设计技术引入了继承的概念。个类从另个类派生出来时,派生类从基类那里继承特性。派生类也可以作为其它类的基类。从个基类派生出来的多层类形成了类的层次结构。注意:C#中,派生类只能从个类中继承。这是因为,在C+中,人们在大多数情况下不需要一个从多个类中派生的类。从多

3、个基类中派生一个类这往往会带来许多问题,从而抵消了这种灵活性带来的优势。C#中,派生类从它的直接基类中继承成员:方法、域、属性、事件、索引指示器。除了构造函数和析构函数,派生类隐式地继承了直接基类的所有成员。看下面示例:using System ;class Vehicle 定义交通工具(汽车)类protected int wheels ;公有成员:轮子个数protected float weight :保护成员:重量public Vehicle();public Vehicle (int w, float g)wheels = w ;weight = g ;public void Speak

4、()Console. WriteLine (交通工具的轮子个数是可以变化的!class Car:Vehicle 定义轿车类:从汽车类中继承int passengers ;私有成员:乘客数public Car(int w , float g , int p): base(w, g)wheels weight = g ;passengers=p ;Vehicle作为基类,体现了汽车”这个实体具有的公共性质:汽车都有轮子和重量。Car类继承了 Vehicle的这些性质,并且添加了自身的特性:可以搭载乘客。二、C#中类继承的实现机制C#中的继承符合下列规则:1、继承是可传递的。如果C从B中派生,B又从

5、A中派生,那么C不仅继承了 B中声明的成员,同样也继承了 A中的成员。Object 类作为所有类的基类。2、派生类应当是对基类的扩展。派生类可以添加新的成员,但不能除去已经继承的成员的定义。3、构造函数和析构函数不能被继承。除此以外的其它成员,不论对它们定义了怎样的访问方式,都能被继承。基类中成员的访问方式只能决定派生类能否访问它们。4、派生类如果定义了与继承而来的成员同名的新成员,就可以覆盖已继承的成员。但这并不因为这派生类删除了这些成员,只是不能再访问这些成员。5、类可以定义虚方法、虚属性以及虚索引指示器,它的派生类能够重载这些成员,从而实现类可以展示出多态性。6、派生类只能从一个类中继承

6、,可以通过接吕实现多重继承。下面的代码是一个子类继承父类的例子:using System ;public class ParentClassI:public ParentClass()Console. WriteLine (父类构造函数。);public void print()Console. WriteLine (T m a Parent Classo )public class ChiIdClass : ParentClasspublic ChildClass()Console. WriteLine(子类构造函数。”)public static void Main()ChiIdClass

7、 child = new ChildClass()chi Id. print ()程序运行输出:父类构造函数。子类构造函数。Im a Parent Classo上面的个类名为ParentClass, main函数中用到的类名为 ChildClasSo要做的是创建一个使用父类ParentClass现有代码的子类ChildClasSo1 .首先必须说明ParentClass是ChildClass的基类。这是通过在ChildClass类中作出如下说明来完成的:“public class ChildClass : ParentClass在派生类标识符后面,用分号:来表明后面的标识符是基类。C#仅支持单

8、继承。因此,你只能指定一个基类。2 . ChildClass的功能几乎等同于ParentClasso因此,也可以说 ChildClass 就是ParentClass。在 ChildClass 的Main()方法中,调用print()方法的结果,就验证这点。该子类并没有自己的print ()方法,它使用了 ParentClass中的print ()方法。在输出结果中的第三行可以得到验证。3 .基类在派生类初始化之前自动进行初始化。ParentClass类的构造函数在ChildClass的构造函数之前执行。三、访问与隐藏基类成员(1)访问基类成员通过base关键字访问基类的成员:调用基类上已被其他

9、方法重写的方法。指定创建派生类实例时应调用的基类构造函数。基类访问只能在构造函数、实例方法或实例属性访问器中进行。从静态方法中使用base关键字是错误的。示例:下面程序中基类Person和派生类Employee都有一个名为Getinfo的方法。通过使用base关键字,可以从派生类中调用基类上的Getinfo方法。using System public class Personprotected string ssn =111-222-333-444”protected string name =张;public virtual void Getlnfo()Console. WriteLine(

10、姓名:0, name)Console. WriteLine(编号:0, ssn) class Employee: Personpublic string id =ABC567EFG23267public override void Getlnfo()/Z调用基类的Getlnfo方法:base. Getlnfo();Console. WriteLine(“成员 ID:0, id)class TestClasspublic static void Main()I:Employee E = new Employee ();E. Getlnfo ();程序运行输出:姓名:张三编号:111-222-33

11、3-444成员 ID: ABC567EFG23267示例:派生类同基类进行通信。using System ;public class Parent!string parentstring;public Parent()(Console.WriteLine(Parent Constructor.)public Parent(string myString)parentstring = myString;Console. WriteLine(parentstring)public void print()Console. WriteLine (T m a Parent Class.,z) publ

12、ic class Child : Parentpublic Child(): base(From Derived)Console. WriteLine(Child Constructor.)public void print()base, print();Console. WriteLine (Im a Child Class.)public static void Main()I:Child child = new Child();child, print ();(Parent)child). print();)程序运行输出:From DerivedChild Constructor.Im

13、a Parent Class.I,m a Child Class.I,m a Parent Class.说明:1 .派生类在初始化的过程中可以同基类进行通信。上面代码演示了在子类的构造函数定义中是如何实现同基类通信的。分号”:和关键字base用来调用带有相应参数的基类的构造函数。输出结果中,第一行表明:基类的构造函数最先被调用,其实在参数是字符串From Derived”。2 .有时,对于基类已有定义的方法,打算重新定义自己的实现。Child类可以自己重新定义print ()方法的实现。Child的 print ()方法覆盖了 Parent中的print方法。结果是:除非经过特别指明,Pare

14、nt类中的print方法不会被调用。3 .在Child类的print ()方法中,我们特别指明:调用的是 Parent类中的print ()方法。方法名前面为base”,一旦使用base关键字之后,你就可以访问基类的具有公有或者保护权限的成员。Child类中的print()方法的执行结果出现上面的第三行和第四行。4 .访问基类成员的另外一种方法是:通过显式类型转换。在Child类的Main()方法中的最后一条语句就是这么做的。记住:派生类是其基类的特例。这个事实告诉我们:可以在派生类中进行数据类型的转换,使其成为基类的个实例。上面代码的最后一行实际上执行了 Parent类中的print()方法

15、。(2)隐藏基类成员想想看,如果所有的类都可以被继承,继承的滥用会带来什么后果?类的层次结构体系将变得十分庞,大类之间的关系杂乱无章,对类的理解和使用都会变得十分困难。有时候,我们并不希望自己编写的类被继承。另一些时候,有的类已经没有再被继承的必要。C#提出了一个密封类(sealed class)的概念,帮助开发人员来解决这问题。密封类在声明中使用sealed修饰符,这样就可以防止该类被其它类继承。如果试图将一个密封类作为其它类的基类,C#将提示出错。理所当然,密封类不能同时又是抽象类,因为抽象总是希望被继承的。在哪些场合下使用密封类呢?密封类可以阻止其它程序员在无意中继承该类。而且密封类可以

16、起到运行时优化的效果。实际上,密封类中不可能有派生类。如果密封类实例中存在虚成员函数,该成员函数可以转化为非虚的,函数修饰符virtual不再生效。让我们看下面的例子:bstract class Aipublic abstract void F();)sealed class B: Apublic override void F()/ F的具体实现代码)如果我们尝试写下面的代码class C: BC#会指出这个错误,告诉你B是一个密封类,不能试图从B中派生任何类。(3)密封方法我们已经知道,使用密封类可以防止对类的继承。C#还提出了密封方法(sealedmethod)的概念,以防止在方法所在类

17、的派生类中对该方法的重载。对方法可以使用sealed修饰符,这时我们称该方法是个密封方法。不是类的每个成员方法都可以作为密封方法密封方法,必须对基类的虚方法进行重载,提供具体的实现方法。所以,在方法的声明中,sealed修饰符总是和override修饰符同时使用。请看下面的例子代码:using System ;class Apublic virtual void F()public virtual void G()Console. WriteLine(A. G) class B: Asealed override public void F()Console.WriteLine(B. F)pu

18、blic override void G()class C: Boverride public void G()Console. WriteLine(C. G)类B对基类A中的两个虚方法均进行了重载,其中F方法使用了 sealed修饰符,成为一个密封方法。G方法不是密封方法,所以在B的派生类C中,可以重载方法G,但不能重载方法F。(4)使用new修饰符隐藏基类成员使用new修饰符可以显式隐藏从基类继承的成员。若要隐藏继承的成员,请使用相同名称在派生类中声明该成员,并用new修饰符修饰它。请看下面的类:public class MyBasepublic int x ;public void My

19、Voke()在派生类中用MyVoke名称声明成员会隐藏基类中的MyVoke方法,即:public class MyDerived : MyBasenew public void MyVoke ();但是,因为字段x不是通过类似名隐藏的,所以不会影响该字段。通过继承隐藏名称采用下列形式之一:a、引入类或结构中的常数、指定、属性或类型隐藏具有相同名称的所有基类成员。b、引入类或结构中的方法隐藏基类中具有相同名称的属性、字段和类型。同时也隐藏具有相同签名的所有基类方法。C、引入类或结构中的索引器将隐藏具有相同名称的所有基类索引器。注意:在同一成员上同时使用new和override是错误的。同时使用n

20、ew和virtual可保证个新的专用化点。在不隐藏继承成员的声明中使用new修饰符将发出警告。示例1:在该例中,基类MyBaseC和派生类MyDerivedC使用相同的字段名x,从而隐藏了继承字段的值。该例说明了 new修饰符的使用。同时也说明了如何使用完全限定名访问基类的隐藏成员。using System ;public class MyBasepublic static int x =55;public static int y =22;public class MyDerived : MyBasenew public static int x =100;/利用 new 隐藏基类的 x p

21、ublic static void Main()/Z打印x:Console.WriteLine(x);访问隐藏基类的x:Console. WriteLine (MyBase. x);打印不隐藏的y:Console. WriteLine(y);输出:1005522如果移除new修饰符,程序将继续编译和运行,但您会收到以下警告:The keyword new is required on , MyDerivedC. x because it hides inherited member MyBaseC. x.如果嵌套类型正在隐藏另种类型,如下例所示,也可以使用 new修饰符修改此嵌套类型。四、多级

22、继承些面向对象语言允许一个类从多个基类中继承,而另些面向对象语言只允许从个类继承,但可以随意从几个接口或纯抽象类中继承。只有C+支持多级继承,许多程序员对此褒贬不。多级继承常会引起继承来的类之间的混乱,继承而来的方法往往没有唯一性,所以C#中类的继承只可以是个,即子类只能派生于个父类,而有时你必须继承多个类的特性,为了实现多重继承必须使用接口技术,下面是对接口的多重继承进行介绍:using System ;定义个描述点的接口interface IPointint xiget ;set ;)int yI:get ;set ;interface IPoint2int yget ;set ;)在po

23、int中继承了两个父类接口,并分别使用了两个父类接口的方法class Point:IPoint, IPoint2(定义两个类内部访问的私有成员变量private int pX ;private int pY ;public Point(int x, int y)pX=x ;pY=y ;定义的属性,IPoint接口方法实现public int xgetreturn pX ;setpX =value ;/IPointl接口方法实现public int ygetreturn pY ;setpY =value ;class Testprivate static void OutPut( IPoint

24、p )Console. WriteLine(x=0, y=l”, p. x, p. y)public static void Main()Point p =new Point(15,30);Console. Write(The New Point is:);OutPut( p );string myName =Console. ReadLine();Console. Write (z,my name is 0, myName)五、多态1、什么是多态面向对象程序设计中的另外一个重要概念是多态性。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。可以把一组对象放到个数组中,然后调用它们的

25、方法,在这种场合下,多态性作用就体现出来了,这些对象不必是相同类型的对象。当然,如果它们都继承自某个类,你可以把这些派生类,都放到个数组中。如果这些对象都有同名方法,就可以调用每个对象的同名方法。同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性。多态性通过派生类重载基类中的虚函数型方法来实现。在面向对象的系统中,多态性是个非常重要的概念,它允许客户对个对象进行操作,由对象来完成一系列的动作,具体实现哪个动作、如何实现由系统负责解释。“多态性”一词最早用于生物学,指同一种族的生物体具有相同的特性。在C#中,多态性的定义是:同一操作作用于不同的类的实例,不同的类将进行不

26、同的解释,最后产生不同的执行结果。C#支持两种类型的多态性:编译时的多态性编译时的多态性是通过重载来实现的。对于非虚的成员来说,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。运行时的多态性运行时的多态性就是指直到系统运行时,根据实际情况决定实现何种操作。C#中,运行时的多态性通过虚成员实现。编译时的多态性为我们提供了运行速度快的特点,而运行时的多态性则带来了高度灵活和抽象的特点。2、实现多态多态性是类为方法(这些方法以相同的名称调用)提供不同实现方式的能力。多态性允许对类的某个方法进行调用而无需考虑该方法所提供的特定实现。例如,可能有名为Road的类,它调用另个类的 Driv

27、e方法。这另个类Car可能是SportsCar或Small Car但二者都提供Drive方法。虽然Drive方法的实现因类的不同而异,但 Road类仍可以调用它,并且它提供的结果可由Road类使用和解释。可以用不同的方式实现组件中的多态性:接口多态性。继承多态性。通过抽象类实现的多态性。接口多态性多个类可实现相同的“接口”,而单个类可以实现个或多个接口。接口本质上是类需要如何响应的定义。接口描述类需要实现的方法、属性和事件,以及每个成员需要接收和返回的参数类型,但将这些成员的特定实现留给实现类去完成。组件编程中的项强大技术是能够在一个对象上实现多个接口。每个接口由一小部分紧密联系的方法、属性和

28、事件组成。通过实现接,组件可以为要求该接口的任何其他组件提供功能,而无需考虑其中所包含的特定功能。这使后续组件的版本得以包含不同的功能而不会干扰核心功能。其他开发人员最常使用的组件功能自然是组件类本身的成员。然而,包含大量成员的组件使用起来可能比较困难。可以考虑将组件的某些功能分解出来,作为私下实现的单独接口。根据接口来定义功能的另个好处是,可以通过定义和实现附加接口增量地将功能添加到组件中。优点包括:1 .简化了设计过程,因为组件开始时可以很小,具有最小功能;之后,组件继续提供最小功能,同时不断插入其他的功能,并通过实际使用那些功能来确定合适的功能。2 .简化了兼容性的维护,因为组件的新版本

29、可以在添加新接口的同时继续提供现有接口。客户端应用程序的后续版本可以利用这些接口的优点。通过继承实现的多态性多个类可以从单个基类“继承”。通过继承,类在基类所在的同一实现中接收基类的所有方法、属性和事件。这样,便可根据需要来实现附加成员,而且可以重写基成员以提供不同的实现。请注意,继承类也可以实现接口,这两种技术不是互斥的。C#通过继承提供多态性。对于小规模开发任务而言,这是个功能强大的机制,但对于大规模系统,通常证明会存在问题。过分强调继承驱动的多态性一般会导致资源大规模地从编码转移到设计,这对于缩短总的开发时间没有任何帮助。何时使用继承驱动的多态性呢?使用继承首先是为了向现有基类添加功能。

30、若从经过完全调试的基类框架开始,则程序员的工作效率将大大提高,方法可以增量地添加到基类而不中断版本。当应用程序设计包含多个相关类,而对于某些通用函数,这些相关类必须共享同样的实现时,您也可能希望使用继承。重叠功能可以在基类中实现,应用程序中使用的类可以从该基类中派生。抽象类合并继承和实现的功能,这在需要二者之一的元素时可能很有用。通过抽象类实现的多态性抽象类同时提供继承和接口的元素。抽象类本身不能实例化,它必须被继承。该类的部分或全部成员可能未实现,该实现由继承类提供。已实现的成员仍可被重写,并且继承类仍可以实现附加接口或其他功能。抽象类提供继承和接口实现的功能。抽象类不能示例化,必须在继承类

31、中实现。它可以包含已实现的方法和属性,但也可以包含未实现的过程,这些未实现过程必须在继承类中实现。这使您得以在类的某些方法中提供不变级功能,同时为其他过程保持灵活性选项打开。抽象类的另一个好处是:当要求组件的新版本时,可根据需要将附加方法添加到基类,但接口必须保持不变。何时使用抽象类呢?当需要一组相关组件来包含一组具有相同功能的方法,但同时要求在其他方法实现中具有灵活性时,可以使用抽象类。当预料可能出现版本问题时,抽象类也具有价值,因为基类比较灵活并易于被修改。示例:实现多态性的程序using System ;public class DrawingBasepublic virtual voi

32、d Draw()Console. WriteLine (T m just a generic drawing object.,?);public override void Draw()Console. WriteLine (,zr m a Line.);public class Circle : DrawingBasepublic override void Draw()Console. WriteLine (Im a Circle.);public class Square : DrawingBasepublic override void Draw()Console. WriteLine

33、 (T m a Square.) public class DrawDemopublic static int Main(string args)DrawingBase dObj = new DrawingBase 4;dObj0= new Line();dObj1= new Circle();dObj2= new Square();dObj3= new DrawingBase();foreach (DrawingBase drawObj in dObj)drawObj. Draw();return 0;说明:上面程序演示了多态性的实现。在DrawDemo类中的Main()方法中,创建了一个数

34、组,数组元素是DrawingBase类的对象。该数组名为dObj,是由四个DrawingBase类型的对象组成。接下来,初始化dObj 数组,由于ine, Circle和Square类都是DrawingBase类的派生类,所以这些类可以作为dObj数组元素的类型。如果C#没有这种功能,你得为每个类创建一个数组。继承的性质可以让派生对象当作基类成员样用,这样就节省了编程工作量。一旦数组初始化之后,接着是执行 foreach循环,寻找数组中的每个元素。在每次循环中,dObj数组的每个元素(对象)调用其Draw()方法。多态性体现在:在运行时,各自调用每个对象的Draw()方法。尽管dObj数组中的

35、引用对象类型是 DrawingBase,这并不影响派生类重载DrawingBase类的虚方法Draw()。在dObj 数组中,通过指向DrawingBase基类的指针来调用派生类中的重载的 Draw()方法。输出结果是:Im a Line.Im a Circle.Im a Square.I,m just a generic drawing object.在DrawDemo程序中,调用了每个派生类的重载的Draw()方法。最后一行中,执行的是DrawingBase类的虚方法Draw()。这是因为运行至U最后,数组的第四个元素是DrawingBase类的对象。3、虚方法当类中的方法声明前加上了 v

36、irtual修饰符,我们称之为虚方法,反之为非虚。使用了 virtua!修饰符后,不允许再有static, abstract,或override修饰符。示例L带有虚方法的类using System ;public class DrawingBasepublic virtual void Draw()Console. WriteLine (这是个虚方法!)说明:这里定义了 DrawingBase类。这是个可以让其他对象继承的基类。该类有一个名为Draw()的方法。Draw()方法带有一个virtual 修饰符,该修饰符表明:该基类的派生类可以重载该方法。DrawingBase类的 Draw()方

37、法完成如下事情:输出语句“这是个虚方法!”到控制台。示例:带有重载方法的派生类using System ;public class Line : DrawingBasepublic override void Draw()Console. WriteLine(画线.)public class Circle : DrawingBasepublic override void Draw()Console. WriteLine (画圆.”)public class Square : DrawingBasepublic override void Draw()说明:上面程序定义了三个类。这三个类都派生

38、自DrawingBase类。每个类都有一个同名Draw()方法,这些Draw()方法中的每一个都有一个重载修饰符。重载修饰符可让该方法在运行时重载其基类的虚方法,实现这个功能的条件是:通过基类类型的指针变量来引用该类。对于非虚的方法,无论被其所在类的实例调用,还是被这个类的派生类的实例调用,方法的执行方式不变。而对于虚方法,它的执行方式可以被派生类改变,这种改变是通过方法的重载来实现的。下面的例子说明了虚方法与非虚方法的区别。using System ;class Apublic void F()Console. WriteLine (A. G) class B: Anew public vo

39、id F()Console. WriteLine(B. F)public override void G()class Teststatic void Main()(B b = new B();A a = b;a. F();b.F();a. G();b.G();)例子中,A类提供了两个方法:非虚的F和虚方法G 类B则提供了一个新的非虚的方法F,从而覆盖了继承的F;类B同时还重载了继承的方法G 那么输出应该是:A.F B.F B.G B.G注意到本例中,方法a.G()实际调用了 B.G,而不是A.G,这是因为编译时值为A,但运行时值为B ,所以B完成了对方法的实际调用。在派生类中对虚方法进行重载

40、先让我们回顾一下普通的方法重载,普通的方法重载指的是:类中两个以上的方法(包括隐藏的继承而来的方法),取的名字相同,只要使用的参数类型或者参数个数不同,编译器便知道在何种情况下应该调用哪个方法。而对基类虚方法的重载是函数重载的另种特殊形式。在派生类中重新定义此虚函数时,要求的是方法名称,返回值类型、参数表中的参数个数、类型顺序都必须与基类中的虚函数完全一致。在派生类中声明对虚方法的重载,要求在声明中加上override关键字,而且不能有 new,static 或 virtual 修饰符。看个用汽车类的例子来说明多态性的实现的程序:using System ;protected float we

41、ight;保护成员重量public Vehicle(int w,float g)I:wheels = w;weight = g;)public virtual void Speak()Console. WriteLine( the w vehicle is speaking!);class Car:Vehicle 定义轿车类int passengers;私有成员乘客数wheels = w;weight = g;passengers = p;public override void Speak()(Console. WriteLine( The car is speaking:Di-di!”)c

42、lass Truck:Vehicle 定义卡车类iint passengers;私有成员乘客数float load;私有成员载重量public Truck (int w, float g, int p, float 1): base(w, g)wheels = w;weight = g;passengers = p;load =1;public override void Speak()1Console. WriteLine ( The truck is speaking:Ba-ba!,z );public static void Main()Vehicle vl = new Vehicle(

43、0,0);Car cl = new Car (4,2,5);Truck tl = new Truck(6,5,3,10);vl. Speak()vl = cl;vl. Speak();cl. Speak();vl = tl;vl. Speak();tl. Speak();)分析上面的例子我们看到: Vehicle类中的Speak方法被声明为虚方法,那么在派生类中就可以重新定义此方法。在派生类Car和Truck中分别重载了 Speak方法,派生类中的方法原型和基类中的方法原型必须完全一致。在Test类中,创建了 Vehicle类的实例vl,并且先后指向Car 类的实例cl和Truck类的实例tl

44、。运行该程序结果应该是:The Vehicle is speaking!The car is speaking:Di-di!The car is speaking:Di-di!The truck is speaking:Ba-ba!The truck is speaking:Ba-ba!这里,Vehicle类的实例vl先后被赋予Car类的实例cl,以及 Truck类的实例tl的值。在执行过程中,vl先后指代不同的类的实例,从而调用不同的版本。这里vl的Speak方法实现了多态性,并且vl. Speak究竟执行哪个版本,不是在程序编译时确定的,而是在程序的动态运行时,根据vl某时刻的指代类型来确

45、定的,所以还体现了动态的多态性。六、练习题1、将下列程序补充完整,使之能正确运行。class peopleprotected string name =;protected int age =0;public people(string name, int age)this, name =_name;this, age = age;public void say(string text)if(text !=) Console. Write(name +”说:我今年“+ age. ToString ()+“岁了!”+text);class teacher : peopleclass runsta

46、tic void Main()teacher anson = new teacher(anson”,28);anson. say (你好);2、实现下图中的Shape层次结构,每个TwoDimensionalShape都应该包含方法Area,用于计算二维图形的面积。每个ThreeDimensionalShape应该包含方法Area和方法Volume,来分别计算三维图形的表面积和体积。使用层次结构中每个实体类的对象的 Shape的引用的数组编写个程序。这个程序应该输出数组中每个对象的String表示。同样,在个循环中处理数组中的所有图形,判断每个图形是二维的还是三维的。如果一个图形是二维的,显示它的 Area,如果一个图形是三维的,显示它的Area和Volume。TwoDimensionalShapeShapeThreeDimensionalShapeCircleSphereCylinderCubeSquareTriangleShape类的层次结构

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!