C#基于对象的程序设计(二)
在这期教学前,请大家先回顾一下上期C#教程:C#基于对象的程序设计(一)
教学目标:面向对象编程是当前计算机界关心的重点,是软件开发方法的主流。本章通过具体实例讲解面向对象的特性——继承、接口和多态性,学生更加容易理解和掌握面向对象的设计方法和编程特点。
教学重点:继承和多态
教学难点:1. 类的继承
- 多态

C#基于对象的程序设计(二)
什么是面向对象编程?
面向对象编程(Object-Oriented Programming),简称OOP,它是通过给程序中加入扩展语句,把函数封装进编程所必需的“对象“中实现的。面向对象的编程语言,使得复杂的工作条例清晰,编写容易。
- 以事物为中心来思考和认识问题
- 按照这些事物的本质特性把它们抽象为对象
- 对同类型的对象抽象其共性,形成类
- 类通过接口和外界联系
在面向对象程序设计中,包含了对象,类,封装,继承,多态性等概念
面向对象的知识点:
-
类与对象
- 在面向对象中,类是封装数据的基本单位
- 通过类的方法可以访问类中的数据
类:
- 相对对象而言,类似于蓝图
- 包含方法和数据
对象:
- 是类的实例
- 使用关键字 new 创建
- 对象具有行为
类
- 把具有共同性质的事物划分为一类,得出一个抽象的概念
- 类即是具有相同属性和服务的一组对象的集合
- 为属于该类的全部对象提供了抽象的描述,其内部包括属性和行为两个主要部分
对象
- 对象是现实世界中一个实际存在的事物
- 对象具有自己的静态特征和动态特征
- 静态特征用某些数据来描述,动态特征用对象的行为或功能来描述
- 静态特征描述为属性,动态特征描述为行为
类的成员:
- 类中的常量、变量、属性或事件不能与其他类成员同名
- 类中的方法名不能和其他类成员同名
主要包括三种成员:
字段:实例字段,静态字段
访问实例字段,直接用对象名.字段名,访问静态字段,不能用对象的名称,而要用类名,即类名.字段名
属性:get(读取 return),set(编写 value)
方法:方法的定义和调用
方法必须定义在类中,包括方法的名称、返回类型、参数列表、方法体。调用当前类的方法,直接使用方法名称,调用其他类的方法,先要创建类的实例——对象,通过对象名.方法名()来调用。
类的修饰符:
- new : 新建类的实例
- public :公有类,表示外界可以不受限制的访问
- protected :保护类,表示可以访问该类或从该类派生的类
- private :私有类,表示只有该类可以访问
- internal :内部类,表示仅能访问本组件(Application或Library)
- abstract :抽象类,表示该类是一个不完整类,只有声明而没有具体的实现。一般用来做其他类的基类,而不单独使用。也就是说抽象基类不需要实例化
- sealed : 密封类,表示该类不能作为其他类的基类,不能派生新的类,但可由其他类继承而来
面向对象的主要特点:
封装
- 面向对象方法的一个重要原则
- 把对象的全部属性和行为组合起来,形成一个独立单位
- 尽可能的隐蔽对象的内部细节,只保留有限的外部接口与外部联系
继承
- 特殊类的对象拥有一般类的全部属性和行为,即为特殊类对一般类的继承
- 继承对于软件复用有着重要意义
多态性
- 一般类中定义的属性和行为,被特殊类继承之后,可以具有不同数据类型或表现出不同的行为
在前面讲过电视的例子,从黑白发展到彩色,又到高清晰,后一代继承了前一代的功能,但是在功能上又有所发展。在面向对象理论中,这就是面向对象的两个重要特征:继承和多态。我们正是通过面向对象的继承性和多态性,开发设计清晰、稳定,易于扩展并且容易维护的软件。
在现有类(称为直接基类)上建立新类(称为派生类)的处理过程即称为继承。在建立新类的过程中,直接基类不作任何改变,派生类继承它的直接基类的成员,而基类的实例构造函数、静态构造函数和析构函数除外。派生类除了继承它的直接基类的成员外,也可以另外定义新成员,以扩展它的直接基类。
继承就是从基类中获取一些公开的成员,如方法和属性。继承的语法如下:
Class Student:Person;//继承类
Class Student:Interface1;//继承接口
C#只允许继承一个基类,但允许继承多个接口。如果子类继承了接口,则必须实现接口中定义的公开成员。所谓公开成员,就时在基类中被定义为public的成员,因为public的作用域可以在子类中生效,而private的作用域则不可。
C#中如何实现继承:
实例:定义Person(基类)
下面我们建立一个Person类,它有三个属性,一个方法,三个私有字段,一个无参数的实例构造函数和一个有三个参数的实例构造函数。
using System;
using System.Windows.Forms;
class Person
{
private string id;
private string name;
private string sex;
public Person()
{}
public Person(string myid,string myname,string mysex)
{
ID=myid;
Name=name;
Sex=mysex;
}
public string Name
{
get{return name;}
set{name=value;}
}
public string Sex
{
get{return sex;}
set{sex=value;}
}
public string ID
{
get{return id;}
set{id=value;}
}
public string PrintPerson()
{
return string.Format("{0} {1} {2}", ID, Name, Sex);
}
}
实例:定义Student(1)
定义一个学生类Student类,由于学生属于人,因此学生具有人的属性。前面我们已经定义了一个Person类,要定义学生类,只需以Person类为直接基类定义一派生类。实现人的属性的代码务须重写,直接继承,这样就可大大节约程序的开发时间。缩短程序的开发周期。
using System;
using System.Windows.Forms;
class Student : Person //指定派生类与直接基类
{
private string stuid;
private string department;
public string Stuid
{
get { return stuid; }
set { stuid = value; }
}
public string Department
{
get { return department; }
set { department = value; }
}
public string Printstudent()
{
return string.Format("{0} {1}", Stuid, Department);
}
public static void Main()
{
string output = "";
//创建新的Student对象
Student student1;
student1 = new Student();
Student student2 = new Student();
//打印出与此人关联的姓名和年龄
output=student1.PrintPerson()+"t";
output += student1.Printstudent() + "n";
//在student1对象上设置一些值
student1.ID = "12569850";
student1.Name = "王飞";
student1.Sex = "男";
student1.Stuid = "0987655";
student1.Department = "计算机";
output = student1.PrintPerson() + "t";
output += student1.Printstudent() + "n";
student2.Name = "张翔";
student2.Sex = "女";
student2.ID = "17683608";
student2.Stuid = "1004501";
student2.Department = "应用外语";
output += student2.PrintPerson() + "t";
output += student2.Printstudent() + "n";
MessageBox.Show(output, "运行结果");
}
}
所有类的基类:object
在.NET Framework中,System.Object是一个特殊的类,它是.NET Framework中所有类的鼻祖。也就是整个类型层次结构的根。每个类不管是.NET Framework提供的,还是自行编写的,都是从System.Object类继承而来的。包括前面的Person类,虽然没有为它指定一个基类,但是编译器会自动把它作为object的派生类。
2. 接口
接口只包含成员的定义,不包含成员的实现。成员是指类中的方法、属性、索引器、事件等。接口的主要目的是为不相关的类提供通用的属性。如C#中的接口“IDbConnection”,用来定义数据源的连接,提供多个未实现的属性和方法,开发者可以自定义两个类“sqlConnection”和“AccessConnection”,并继承IDbConnection接口,那么这两个类就具备相同的成员,但实现内容不同,因为sqlConnection用来连接SQL Server数据库,而AccessConnection用来连接Access数据库。下面代码演示一个简单的接口定义。其中“interface”时定义接口的关键字。
interface Iconnection
{
Public string DatabaseName;
Public string AddDataBase();
Public string GetDataBaseConn();
}
接口就好像一个模板,提供基本成员的结构,但并没有添加实质性的内容。由于C#不能实现多个类的继承,而可以实现多个接口的继承,所以使用接口时可以让一个类具备两个以上基类的唯一方式。
用C#如何创建接口
现在演示用C#创建一个接口,步骤如下:
- 打开应用程序,在解决方案资源管理器中,右击根目录,在弹出的快捷菜单中,依次选择“添加|新建项”菜单命令,打开项模板对话框。
- 选中“接口”模板,默认名称为“cs”,单击“添加”按钮,此时在根目录下生成一个“Interface1.cs”类文件,默认代码如下所示:
using System;
using System.Collections.Generic;
using System.Text;
namespace Interface_eg
{
interface Interface1
{
}
}
- 默认生成一个空的接口“Interface1”,设计一个公司员工的接口定义,代码如下所示:
interface Interface1
{
public string EmployeeName;//员工姓名
public void AddEmployee();//添加员工
public void DelEmployee();//删除员工
public string EmployeeAddress();//员工住址
}
-
按“Ctrl+S”键保存代码
补充:创建和使用接口
-
创建一项目InerfaceApp
-
声明接口IThing
namespace InerfaceApp
{
public interface IThing
{
string Type { get; }
string TellAboutSelf();
}
}
(3) 实现接口。
using System;
using System.Windows.Forms;
public class Temperatrue : IThing
{
protected float m_Value;
public Temperatrue() { }
public Temperatrue(float f)
{
m_Value = f;
}
public float Value
{
get { return m_Value; }
set { m_Value = value; }
}
public float Celsius
{
get { return (m_Value - 32) * 5 / 9;}
set { m_Value = value * 9.0f / 5 + 32; }
}
public string Type
{
get { return "温度"; }
}
public String TellAboutSelf()
{
return "华氏温度" + string.Format("{0:n1}", Value) + "摄氏温度" + string.Format("{0:n1}", Celsius);
}
}
public class Manager : IThing
{
private string name;
private decimal salary;
private DateTime bornDay;
public Manager() { }
public Manager(string name, decimal salary, int year, int month, int day)
{
this.name = name;
this.salary = salary;
bornDay = new DateTime(year, month, day);
}
public string Name
{
get { return name; }
set { name = value; }
}
public decimal Salary
{
get { return salary ; }
set { salary= value; }
}
public DateTime BornDay
{
get { return bornDay; }
set { bornDay = value; }
}
public string Type
{
get { return "经理"; }
}
public string TellAboutSelf()
{
return "姓名:" + Name + "出生日期:" + BornDay.ToShortDateString() + "基本工资:" + String.Format("{0:c}", salary);
}
}
-
添加测试类
namespace InerfaceApp
{
class InterfaceTest
{
static string Showinfo(IThing[] b)
{
String output = "";
for (int i = 0; i < b.Length; i++)
{
output +="n"+b [i].Type +":"+b[i].TellAboutSelf ()+"n";
}
return output ;
}
public static void Main(string[] args)
{
IThing[] thinges = new IThing[4];
Manager obj1 = new Manager("王菲", 8000.6M, 1970, 6, 15);
Manager obj2 = new Manager("李丽", 10000, 1972, 2, 27);
Temperatrue obj3 = new Temperatrue(32);
Temperatrue obj4 = new Temperatrue(0);
thinges[0] = obj1;
thinges[1] = obj2;
thinges[2] = obj3;
thinges[3] = obj4;
string output = Showinfo(thinges);
MessageBox.Show(output, "输出结果");
}
}
}
3. 多态
多态是指类可以有多种形态,通过修改可以形成多个方法。当派生类从基类继承时,它会获得基类的所有方法、字段、属性和事件。若要修改父类的数据和行为,通常有两种选择,可以创建新的成员替换基类成员,或者可以重写虚拟的基类成员。
如果要替换基类成员,需要使用new关键字。下面代码演示了GetName方法的两种形态,一种是返回父级名称,一种是返回子级名称。
class ParentClass//父类
{
public string GetName()
{ return "父级名称"; }
}
class SonClass:ParentClass//子类
{
public string GetName()
{ return "子级名称"; }
}
如果要重写虚拟的基类成员,需要两个条件,父级成员使用关键字“virtual”,而子级成员使用关键字“override”。下面演示这种形式下的GetName方法,代码如下所示:
class ParentClass//父类
{
public virtual string GetName()
{ return "父级名称"; }
}
class SonClass:ParentClass//子类
{
public override string GetName()
{ return "子级名称"; }
}
用C#如何实现多态(P70)
使用多态要注意被调用的究竟是哪一种形态。本例通过两个类和一个方法,演示多态的使用,实现步骤如下:
(1)创建类“Employee“,表示公司里的员工。它包含一个虚方法getDepart。代码如下所示:
Class Employee
{
Public virtual string getDepart ()
{ return “总公司”;}
}
(2)创建类“MarketEmployee“,表示市场部员工。它重写了父类的getDepart方法。代码如下:
Class MarketEmployee:Employee
{
Public override string getDepart ()
{return “市场部”;}
}
(3)下面的代码演示了如何调用这两种形态的方法,注释中还给出了运行结果。
Employee myee=new Employee();//创建父类 String str1=myee.getDepart();//结果为“总公司“ MarketEmployee yee=new MarketEmployee();//创建子类 String str2=yee.getDepart();//结果为“市场部“。
4. 面向对象开发的简单实例
本节以一个非常简单的案例,介绍如何在日常应用开发中采用面向对象技术。
实现步骤:
- 新建一个项目“OOPSample”
- 在解决方案资源管理器的根目录下,添加类“cs”,设计员工的共性。
class Employee
{
//私有属性的设计
private int _id;
private string _name;
private int _age;
private string _address;
public int EmployeeID //员工号
{
get { return _id; }
set { _id = value; }
}
public string Name //员工姓名
{
get { return _name; }
set { _name = value; }
}
public int Age //员工年龄
{
get { return _age; }
set { _age = value; }
}
public string Address //员工地址
{
get { return _address; }
set { _address = value; }
}
public void WorkOn()
{
//上班操作的代码
}
public void WorkOff()
{
//下班操作的代码
}
}
(3)在根目录下添加一个类“SaleEmployee.cs”,设计销售部员工的特性。
class SaleEmployee:Employee
{
private int _salecount;
public int SaleCount //销售额
{
get { return _salecount; }
set { _salecount = value; }
}
public void Sale()
{
//销售操作的代码
}
}
(4)在根目录下添加一个类“BuyEmployee.cs”,设计采购部员工的特性。
class BuyEmployee:Employee
{
public void Buy()
{
//采购操作的代码
}
}
(5)下面的代码演示如何在应用程序中使用这两个部门的类。
SaleEmployee mysale = new SaleEmployee();//实例化销售部员工类 mysale.Name = "销售员"; mysale.Sale(); //销售操作 mysale.WorkOff(); //下班 label1.Text=mysale.SaleCount.ToString(); //显示此员工的销售额 BuyEmployee mybuy = new BuyEmployee();//实例化采购部员工类 mybuy.Name = "采购员"; mybuy.WorkOn();//上班 mybuy.Buy();//采购
上机实训。
class Boat
{
private string registrationNo;
float length;
string manufacturer;
int year;
public string RegistrationNo
{
get { return registrationNo; }
set { registrationNo = value; }
}
public float Length
{
get { return length; }
set { length = value; }
}
public string Manufacturer
{
get { return manufacturer ; }
set {manufacturer = value; }
}
public int Year
{
get { return year; }
set { year = value; }
}
public Boat() { }
public virtual string ToallString()
{
return string.Format("{0} {1} {2} {3}", RegistrationNo, Length, Manufacturer, Year);
}
}
class Sailboat : Boat
{
int keeldepth;
string id;
string type;
public int KeelDepth
{
get { return keeldepth ; }
set { keeldepth = value; }
}
public string ID
{
get { return id; }
set {id = value; }
}
public string Type
{
get { return type ; }
set { type = value; }
}
public Sailboat() { }
public override string ToallString()
{
return string.Format("{0} {1} {2} ", KeelDepth ,ID,Type );
}
}
class Powerboat : Boat
{
int numberEngins;
string fuletype;
public int NumberEngins
{
get { return numberEngins ; }
set { numberEngins = value; }
}
public string FuleType
{
get { return fuletype; }
set { fuletype = value; }
}
public Powerboat() { }
public override string ToallString()
{
return string.Format("{0} {1} ", NumberEngins ,FuleType );
}
}
class Program
{
static void Main(string[] args)
{
string output = "";
Sailboat sboat = new Sailboat();
sboat.KeelDepth = 10;
sboat.ID = "123";
sboat.Type = "inboard";
output=sboat.ToallString();
MessageBox.Show(output);
}
}
1、IT大王遵守相关法律法规,由于本站资源全部来源于网络程序/投稿,故资源量太大无法一一准确核实资源侵权的真实性;
2、出于传递信息之目的,故IT大王可能会误刊发损害或影响您的合法权益,请您积极与我们联系处理(所有内容不代表本站观点与立场);
3、因时间、精力有限,我们无法一一核实每一条消息的真实性,但我们会在发布之前尽最大努力来核实这些信息;
4、无论出于何种目的要求本站删除内容,您均需要提供根据国家版权局发布的示范格式
《要求删除或断开链接侵权网络内容的通知》:https://itdw.cn/ziliao/sfgs.pdf,
国家知识产权局《要求删除或断开链接侵权网络内容的通知》填写说明: http://www.ncac.gov.cn/chinacopyright/contents/12227/342400.shtml
未按照国家知识产权局格式通知一律不予处理;请按照此通知格式填写发至本站的邮箱 wl6@163.com