《Beginning c# Objects》读书笔记系列
假定已经正确而完整地通过Student类对"学生"的基本要素进行了建模,且已经用C#编写了该类.Student类的简板代码如下:
using System;2
piblic class Student3
{4
private string name;5
private string studentId;6
//

7

8
public string Name{9
get {10
return name;11
}12
set {13
name = value;14
}15
}16
public string StudentId{17
get { 18
return studentId;19
}20
set {21
studentId = value;22
}23
}24
//

25
}再进一步假设Student了的代码经过严格的检测,没有任何缺陷,而且已经用到一些应用程序中:例如,学生选课系统、学生交费系统、和校友录等等.
对研究生建模是一种新的需求.研究生和我们已对之建模的普通学生之间的区别在于
* 在进入研究生阶段前,该生获得过什么本科学位;
* 在何处获得这个学位.
用于描述研究生的其他信息--姓名、编号、存取这些信息的attribute和描述学生行为的方法等----与已经编好的代码的Student类没有区别,因为研究生到底也是学生.
继承手法:
使用面向对象编程语言,我们就能利用继承的好处来解决问题.继承是一种强大的机制,它通过指出新旧类之间的不同之处,在旧类基础上定义一个新类.使用继承手法,我们就能声明一个继承Student类所有特性的GraduateStudeng类.GraduateStudent类只需要照管俩个与研究生相关的attribute----undergraduateDegree和undergraduateInstituion.在C#类声明中,用冒号后面跟基类的名称来标示继承关系.
pbulic class GraduateStudent : Student{
//声明俩个和Student类不同的attribute
private string undergraduateDegree;
private string undergraduateInstitution;//Institution 机构
//
还有这俩个attribute的proerty
public string UndergraduateDegree{
get{
return undergraduateDegree;
}
set{
undergraduateDetree = value ;
}
}
public string UndergraduateInstitution{
get{
return undergraduateInstitution;
}
set{
undergraduateInstitution = value ;
}
}
}

继承的妙处:
*派生类要比非继承的类更为简洁.
*通过继承的方式,我们能够重用和扩展已彻底测试过的代码,且无须改之;
*最妙的是,即使我们没有一个类的代码,也可以从中派生出新类!只要有编译好的类,继承机智便可管用;扩展一个类时并不需要其源代码.这是面向对象语言带来的生产力显著提升的途径之一:
*最后,如前面所示,分类是人类组织信息的自然方式;所以,惟有按照这种方式组织软件,并使其更为直观,放可达到易于维护和扩展的目的.
覆载:
覆载可以不通过修改方法截面而改变一个方法或一个pripertu的内部工作机理.例如,假设我们为Student了日定义了一个Print方法,用来打印一个学生对象的所有attribute值.
{
//Attributes.
private string name;
private string studentId;
private string majorField;
private double gpa;
//等等
//这些attribute的property也已经提供,此处略
public void print(){
//打印Student类的所有attribute的值
//注意get访问器的用法
Console.WriteLin("Student Name:"+Name+"\n"+
"Student No.:"+StudentId+"\n"+
"Major Field:"+MajorField+"\n"+
"GPA:"+Gpa);
}
}
上例中的Print方法假设Student类的所有attribute已覆值.Property访问器用来存取相关的attribute值,而不是直接存取attribute.
Student类的所有派生类都会继承这个方法,但是,还有一个问题:我们给GraduateStudent派生增添俩个新attribute----undergraduateDetree 和undergraduateInstitution.如果只是采取让GraduateStudent类原封不动的继承Student类Print方法这种懒方法,则在调用GraduateStudent的Pring方法时,总会答应从Student类继承的四个attribute----name、studentId、major和gpa因为Print方法的代码只能打印这些attribute值。然而,我们期望的是GraduateStudent的Print方法不但能打印这四个attribute值,还能打印underagraduateDetree和undergrateInstitution俩个增添的attribute值。
使用面向对象语言,我们能覆载,或者说替换GraduateSutdent类从Student类继承下来的Pring方法。要覆盖一个方法,必须先在所属类的基类中,使用virtual关键字把该方法声明为虚方法。声明一个虚方法,表示该方法可能(而非必须)被派生类所覆载。
派生类可以在方法声明中使用override关键字来重新实现基类虚方法。派生类中的覆载方法必须声明为何基类方法拥有同样的作用域、返回值、名称和参数列表。
我们来看看GraduateStudent类会怎么覆载Student类的Pring方法:
public class Student
{
//Attributes.
private string name;
private string studentId;
private string majorField;
private double gpa;
//等等
//这些attribute的property也已经提供,此处略
//Student 类的Print方法被声明为虚方法,
//可以被派生类覆载
public virtual void print(){
//打印Student类知道的attribute的值,注意get访问器的用法
//注意get访问器的用法
Console.WriteLin("Student Name:"+Name+"\n"+
"Student No.:"+StudentId+"\n"+
"Major Field:"+MajorField+"\n"+
"GPA:"+Gpa);
}
}
public class GraduateStudent : Student
{
string undergraduateDegree;
string undergraduateInstitution;
//property已赋值,此处从略
//现在覆载Student类的Pring方法;
//注意override 关键字
public override void pring(){
//打印GraduateStudent类知道的attribute值;
//即从Student类继承的和自己声明的.
Console.WriteLie("Student Name:"+Name+"\n"+
"Student No.:"+StudentId+"\n"+
"Major Field:"+MajorField+"\n"+
"GPA:"+Gpa+"\n"+
"Undergrad.Deg.:"+UndergraduateDegree+"\n"+
"Undergrade.Inst.:"+UndergraduateInstitution);
}
}
GraduateStudent类的Print方法,就这样覆载/替代了送Student类继承的版本.
上例代码不太完美,因为GraduateStudent类Print方法的前四行重复了Student类Print方法的代码。应该避免代码冗余,因为他会让维护变成一场噩梦:如果想修改一处代码,就要拼命记得修改不知道什么地方的相同代码,最郁闷的是,如果忘记修改别处的相同代码,就会引起代码逻辑矛盾。我们应避免代码冗余,但却鼓励尽可能的重用代码。所以GraduateStudent类的Pring方法其实应该这样写:
public class GraduateStudent : Student
{
//细节从略

public overide void print(){
//调用基类的Pring方法,重用代码

base.Print();
//然后继续打印派生类特有的attribute
Console.WriteLine("Undergrad.Deg.:"+UndergraduateDegree+"\n"+
"Undergrad.Inst.:"+UndergraduateInstitution);
}
}
我们使用C#关键字base做为方法调用的指示符:
base.method Name(arguments);
注意:在所有情况下,存取的作用范围、返回值和方法前必须保持一致----public void Pring()---这样覆载才能起作用。


浙公网安备 33010602011771号