第六章 面向对象程序设计基础.

Slides:



Advertisements
Similar presentations
网络应用程序设计 2014 JavaBean. JavaBean 及其属性 JavaBean 就是一种 Java 的组件技术 JavaBean 是 Java 类 JavaBean 通过约定的方法名实现属性功能 简单属性 void setXxx(Type value) Type getXxx() boolean.
Advertisements

第四章 类 和 对 象.
鄭士康 國立台灣大學 電機工程學系/電信工程研究所/ 資訊網路與多媒體研究所
课程 要求 参考 书目 课程 内容 课程 练习.
面向对象的C++程序设计基础 第 4 章 继承与派生.
四資二甲 第三週作業 物件導向程式設計.
Oracle数据库 Oracle 子程序.
C#程序设计 10软件1、2班 王槐彬 计算机工程学院.
7.2 访问控制 —— 公有继承 公有继承练习 //Point.h #ifndef _POINT_H #define _POINT_H class Point { //基类Point类的定义 public: //公有函数成员 void initPoint(float x = 0, float.
内容提要 代码重用 类的继承 多态 抽象类 多重继承 虚拟继承. 常宝宝 北京大学计算机科学与技术系
第14章 c++中的代码重用.
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
全国计算机等级考试 二级基础知识 第二章 程序设计基础.
第10讲 Java面向对象编程基础(4) 教学目标 主要内容.
鄭士康 國立台灣大學 電機工程學系/電信工程研究所/ 資訊網路與多媒體研究所
Using C++ The Weird Way Something about c++11 & OOP tricks
第5章 异常处理 王德俊 上海交通大学继续教育学院.
4.3函数 4.3.1函数的概念及定义 1、函数的概念: 可以被其它程序调用具有 特定功能的一段相对独立的 程序(模块),称函数。
第四章 在 C# 中实现 OOP 概念.
第三章 C#面向对象初级编程 面向对象得程序设计越来越受到编程人员的喜爱。类和对象是面向对象程序设计中的重要概念。封装性、继承性和多态性是面向对象的特点,本章旨在全面说明C#编写面向对象程序设计的方法。
C#程序设计基础 $3 成员、变量和常量.
第9章 多线程 王德俊 上海交通大学继续教育学院.
第三章 在C#中实现面向对象的概念.
第11讲 类的继承 1. 类的继承的概念 2. 类的单继承机制 3. 单继承中的构造函数和析构函数.
走进编程 程序的顺序结构(二).
辅导课程六.
C#面向对象程序设计 $7 继承和多态性.
類別的繼承 Vehicle Car.
第6章 继承和接口设计 6.1 继 承 6.2 多态性 6.3 抽象类 6.4 接口 6.5 接口在集合排序中的应用.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
第五讲 四则运算计算器(一) 精品教程《C#程序设计与应用(第2版)清华大学出版社 谭恒松 主编
第八章 继承与派生 丘志杰 电子科技大学 计算机学院 软件学院.
泛型委托 泛型接口、方法和委托.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
第六章 属性、索引器、委托和事件.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
第11讲 类的继承 1. 类的继承的概念 2. 类的单继承机制 3. 单继承中的构造函数和析构函数.
$9 泛型基础.
C++复习3 ----类的继承与派生.
C#面向对象程序设计 $6 深入理解类.
C#程序设计基础 $3 成员、变量和常量.
VB与Access数据库的连接.
第八讲 面向对象程序设计(一) 精品教程《C#程序设计与应用(第2版)清华大学出版社 谭恒松 主编
分裂对象模型 C++ otcl.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
第4章 Excel电子表格制作软件 4.4 函数(一).
本节内容 类成员的访问控制 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
第九节 赋值运算符和赋值表达式.
Chapter 18 使用GRASP的对象设计示例.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
Visual Basic程序设计 第13章 访问数据库
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
辅导课程十五.
第二章 Java基本语法 讲师:复凡.
第7章 模板 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
本节内容 C语言的汇编表示 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
第6單元 6-1 類別的繼承 (Class Inheritance) 6-2 抽象類別 (Abstract Class)
基于列存储的RDF数据管理 朱敏
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
本节内容 动态链接库 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
WEB程序设计技术 数据库操作.
创建、启动和关闭Activity 本讲大纲: 1、创建Activity 2、配置Activity 3、启动和关闭Activity
第六讲 酒店客房管理系统(二) 教育部“十二五”职业教育国家规划教材
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
Presentation transcript:

第六章 面向对象程序设计基础

本章内容 6.1 类和对象的基本特性 6.2 类的建立和实例化 6.3 继承和派生 6.4 综合应用 6.5 自主学习—重载与重写

面向过程 面向对象 面向对象 将现实世界的事物抽象成对象,现实世界中的关系抽象成类、继承,帮助人们实现对现实世界的抽象与数字建模。 用“对象”的思想方法来分析和设计程序。 分析解决问题所需步骤 用函数实现步骤 使用时按顺序依次调用函数 例如: 汽车启动; 汽车到站; 什么是对象

对象 颜色 型号 出厂日期 开机 切换频道 关机 生活中的“对象”就是东西,任何东西都可以看成 是对象 把一个东西看成对象,可以孤立地观察它的性质、 行为,进而研究它与其他对象的关系。 颜色 型号 出厂日期 开机 切换频道 关机

对象 处理文件 在程序中使用对象的概念 程序看成是很多对象相互作用 的结果。 播放声音 显示文件

类 类是对象的“蓝图”。 类规定了对象的特征。 对象是根据“蓝图”生产出的产品。 从同一个类产生出的对象具有相同的结构和规格, 却在某些特性上有其不同之处。 总之,类是现实生活中一类具有共同特征的事物的 抽象。 类是对象的模板,对象是类的实例。 实例化 月饼模型(类) 月饼(对象)

面向对象的特点—封装 遥控器控制电视,只 需按下按钮就能切换 频道 不需要知道电视如何 接收信号和搜索频道 使用者把电视看成一 个对象,如同一个 “黑盒子”,只需要 知道如何操作它即可。

将数据、属性、事件和方法集合在一个类中。 笔记本电脑的封装性: 封装了CPU、内存、硬盘、网卡、声卡等 提供了USB接口、网卡接口、音频接口等 面向对象程序设计的封装性: 将数据、属性、事件和方法集合在一个类中。 数据 属性 事件 方法

如:“TextBox”类 } 类的定义 对象的声明 TextBox textBox1; Class TextBox { …… } 类的定义 对象的声明 TextBox textBox1; 对象实例化 textBox1 = new TextBox(); 对象属性设置 调用方法 textBox1.focus(); 响应事件 textBox1.Name = "textBox1"; textBox1.Text = "我是No.1"; void textBox1_KeyPress(……) { …… }

面向对象的特点—继承 基类(父类)派生类(子类) 电视机不断发展 黑白彩色高清 但声音、图像的功能一 直延续下来 后一代“继承”前一代 的功能并有所发展 旧电视派生出新电视 新电视继承了旧电视 派生 继承 继承 派生 基类(父类)派生类(子类)

继承性示例: 继承 派生 CSCircle: 继承了CSPoint所有成员 新增了数据成员r 方法Set

(续) 我的对外“接口”稳定 旧款录像机与旧款电视机相连 旧款录像机也可与新款电视机相连 电视的音频/视频输入输出接口基本不变 对象的对外接口稳定 对象在各自发展的同时, 还可以进行交互。 我的对外“接口”稳定

面向对象的特点—多态 同一操作作用于不同的类的对象,将产生不同的执 行结果,即不同类的对象收到相同的消息时,得到 不同的结果。 汪 喵

多态(2) 开始讲课 开始听课

默认(省略)时,为internal,只能在当前项目中使用;若为public则可在其他项目中使用 6.2类的定义 class 类名 [:基类] { 数据成员的说明 属性的定义 方法的定义 事件的定义 } 默认(省略)时,为internal,只能在当前项目中使用;若为public则可在其他项目中使用

在哪里定义类?(1) 放在命名空间(顶级类) 创建类文件(顶级类)

在哪里定义类?(2) 在类Program中定义(嵌套类)

“轿车”类的数据成员 颜色 排量 类型 字段名称 数据成员(字段):在类中存储信息的成员 class Car { Private string color; Private float displacement; Private Datetime releasedate; } 排量 出厂日期 类型 访问修饰符 字段名称

成员的访问修饰符 成员声明的可选部分 指明程序的其他部分如何访问成员 手机 private protected internal 访 问 权 限 private 私有的,只能在其声明的类中可以访问,不能在类之外访问。 protected 保护的,只能在其声明的类及其派生类中可以访问。 internal 仅限于此程序(exe或dll) protected internal protected或internal,仅限于此程序或派生类中 public 公共的,访问不受限制。 公用电话

“轿车”类的方法 动作:行驶 返回值类型 形式参数列表 访问修饰符 方法名 设计“方法”用于表达对象的动作。 Class Car { …… public void Run() Console.WriteLine(“Running now.”); } 返回值类型 形式参数列表 访问修饰符 方法名

6.2.2 方法 方法实例1:mymove() 方法实例2:printa()

调用方法所需的参数及每个参数的数据类型 返回结果的数据类型 [访问修饰符] 返回值类型 方法名([形式参数列表]) { 方法体 } 方法体中使用return语句返回函数值: return 表达式; 或 return(表达式); 或 return;//可在无返回值时使用 无返回值,返回值类型为void,可省略return语句; 有返回值,返回值类型不为void,方法中必须有return语句

参数与返回值 参数1 返回值 方法 参数2

形式参数(形参) 形参列表位于方法名后的括号内,指明调用该方法所 需参数及每个参数的数据类型 多个参数间用逗号分隔 无参数时,括号不能省略 public void Run(string road) { Console.WriteLine(“我在”+road+”上行驶”); }

Public double sin(double x) 形参 方法的调用 Public double sin(double x) { sx=…x.. ; return sx; } static void Main(string[] args) { y=sin(3.14/2); Console.Write (“结果为”+y); } 调用指定对象的方法: 对象.方法名([实在参数表]) 方法调用时: 按照实在参数(实参)的顺序,依次将实参传递给 对应的形参,二者的数据类型保持一致 执行方法中的语句, 在遇到return语句时,或者执行完所有语句后,返 回调用此方法的程序代码段,同时返回一个值。 实参

例 方法的调用 形参 实参 class Myclass { public int Sum(int x, int y) return x + y; } public float Avg(float input1, float input2) return (input1 + input2) / 2.0F; static void Main(string[] args) { Myclass myC = new Myclass(); int z = 8; Console.WriteLine("Sum:{0} and {1} is {2}", 4, z, myC.Sum(4, z)); Console.WriteLine("Avg:{0} and {1} is {2}",4,z,myC .Avg (4,z)); }

例6.4 方法的调用 static void Main(string[] args) { CSPoint1 p1 = new CSPoint1(); CSPoint1 p2 = new CSPoint1(); p1.SetValue(0, 0); p2.SetValue(1, 1); double s = p1.Distance(p2); Console.WriteLine(s); Console.ReadKey(); } 例6.4 方法的调用 class CSPoint1 { private double x; private double y; public void SetValue(int a, int b) x = a; y = b; } public double Distance(CSPoint1 p) double s = Math.Sqrt((x - p.x) * (x - p.x) + (y - p.y) * (x - p.y)); return s;

public void Run(string road) 参数传递 road “S20高速” 调用方法时(通过参数)将数据传递给被调用方法 值形参:参数声明时无修饰符 引用形参:用ref修饰符说明 输出形参:用out修饰符说明 形参数组:用params修饰符说明 public void Run(string road) car1.Run(“S20高速”);

值形参 无修饰符 按值传递过程中,实参和形参各自占用不同的内存空 间 只把实参的值复制给对应的形参 执行期间,形参的值改变对实参无任何影响 例6.5

class Test { public static void swap(int x, int y) int temp; temp = x; x = y; y = temp; } 例6.5 开始调用时: 3 k x 4 l y static void Main(string[] args) { int k = 3; int l = 4; Test.swap(k, l); Console.WriteLine("k = {0},l = {1}", k, l); Console.Read(); } 3 4 k x l y 结束调用时:

引用形参 ref修饰符 值传递时,实参与形参使用的是相同的内存单元 在执行期间,若形参的值发生变化,实参的值也 会发生相同的变化 引用形参实质上是对应实参的别名,他们相当于 同一个变量或对象 当形参是引用形参时,定义和调用时都必须使用 ref关键字。 例6.6

例6.6 k x y l k x y l class Test { int temp; temp = x; x = y; y = temp; public static void swap(ref int x, ref int y) int temp; temp = x; x = y; y = temp; } 例6.6 开始调用时: k x 3 y l 4 static void Main(string[] args) { int k = 3; int l = 4; Test.swap(ref k, ref l); Console.WriteLine("k = {0},l = {1}", k, l); Console.Read(); } 结束调用时: k x 4 y l 3

输出形参 m=7,n=-1 out修饰符 主要用于将数据从被调用函数传递到调用函数。 定义和调用时都必须使用out关键字。 class Test { public static void arith(int x, int y, out int sum, out int difference) sum = x + y; difference = x - y; } 输出形参 out修饰符 主要用于将数据从被调用函数传递到调用函数。 定义和调用时都必须使用out关键字。 m=7,n=-1 static void Main(string[] args) { int k = 3, l = 4; int m, n; Test.arith(k, l, out m, out n); Console.WriteLine("m = {0},n = {1}", m, n); Console.Read(); }

学生类属性例6.9 属性的定义格式 访问修饰符同数据成员的5种修饰符 根据get和set访问器是否存在,属性分为: get访问器:定义属性的读操作!相当于一个具有返回值的无参数方法,需要有return语句返回属性值 属性的定义格式 访问修饰符同数据成员的5种修饰符 根据get和set访问器是否存在,属性分为: [访问修饰符] 类型 属性名 { [ get{get访问器体}] [ set{set访问器体}] } set访问器:定义属性的写操作!相当于一个只有一个参数并且返回值为void类型的方法 读写属性:包含get和set访问器的属性 只读属性:只有get访问器的属性 只写属性:只有set访问器的属性 学生类属性例6.9

属性和字段的区别 Value:表示对属性进行写操作时提供的参数 class Car car1. Color =“red”;时,value即“red” class Car { private string color1; private float displacement1; private Datetime releasedate; public string Color get {return color1;} set {color1=value;} } public string Displacement get {return displacement1}; set {displacement1 =value}; 属性和字段的区别

属性与字段的区别 既然可以声明一个public字段以实现读写,为什么 还要采用属性? public字段完全放开,任何人都可以对它进行读写 class Car { …… public DateTime ReleaseDate get return releasedate; } 既然可以声明一个public字段以实现读写,为什么 还要采用属性? public字段完全放开,任何人都可以对它进行读写 而属性控制灵活,若只提供get方法则只支持读; 只提供set方法则只支持写;都提供则支持读写。 1.属性比字段读写提供更多的控制 如Car类的releasedate字段,一旦出厂便已确定,我们希望它只读而不能修改。所以把releasedate字段设为private,而提供一个只读的ReleaseDate属性

续 例如,希望为Car类提供一个Age(使用年份)属 性,而且随着时间发展,这个属性会不断变化而更 新。 年份=当前日期-出厂日期 2.属性拥有一些方法的特征,让它达到直接读写字段无法达到的效果 例如,希望为Car类提供一个Age(使用年份)属 性,而且随着时间发展,这个属性会不断变化而更 新。 年份=当前日期-出厂日期 提供Age属性: 属性的读操作中包含了计算的车龄的操作。且车龄 只读,不能人为设置。 public TimeSpan Age { get return(DateTime.today-ReleaseDate); }

6.2.5 对象 类Car的对象 car1 car1 创建对象 如Car car1 = new Car();

Font f2 = new Font("黑体", 20,FontStyle.Bold); 构造函数的特点: 构造函数的作用:对象初始化的专用函数 Font f1 = new Font("黑体", 20); Font f2 = new Font("黑体", 20,FontStyle.Bold); 构造函数的特点: 1)构造函数名:构造函数的名称与类名相同 , 并且不能指定函数类型(也不能使用void) 2) 可以重载:可以定义多个构造函数 总要有不同的地方:或参数个数不同,或参数类型不 同的 3)构造函数调用: 创建对象时系统自动调用,程序中不能直接调用。 新车出厂的时候,通过构造函数来初始化其颜色、排量、出厂日期。 class Car {…… public Car() //构造函数 { color=“gray”;//设置新Car对象的颜色 displacement=2.0;//设置排量 Releasedate=DateTime.today;//设置出厂日期 }

构造函数(续) 构造函数不设返回值 可以编写有参数的构造函数,让它根据参数来初始 化类的字段 构造函数在创建类的对象时,通过new来调用 public Car() //无参数的构造函数 { color=“gray”;//设置新Car对象的颜色 displacement=2.0;//设置排量 Releasedate=DateTime.today;//设置出厂日期 } public Car(string Color,float Diaplacement) //有参数的构造函数 color=Color;//设置新Car对象的颜色 displacement= Diaplacement;//设置排量 构造函数不设返回值 可以编写有参数的构造函数,让它根据参数来初始 化类的字段 构造函数在创建类的对象时,通过new来调用 car1:gray,2.0 Car2:red,2.4 Car car1 = new Car(); //调用无参数的构造函数 Car car2 = new Car(“red”,”2.4”) //调用有参数的构造函数

例6.11 创建并访问对象 应用例6.5所完成的Student类,当选择“数据赋予 对象”按钮时,若成绩小于60分则用MessageBox 提示“成绩不及格”;当选择“输出对象数据”按 钮时,用MessageBox输出各属性的值。

例6.12 通过代码在窗体上生成文本框

6.2.6 构造函数 构造函数的作用:对象初始化的专用函数 构造函数的特点: 1)构造函数名:构造函数的名称与类名相同 , 6.2.6 构造函数 public Form1() { InitializeComponent(); } 构造函数的作用:对象初始化的专用函数 构造函数的特点: 1)构造函数名:构造函数的名称与类名相同 , 并且不能指定函数类型(也不能使用void) 2) 可以重载:可以定义多个构造函数 总要有不同的地方:或参数个数不同,或参数类型不 同的 3)构造函数调用: 创建对象时系统自动调用,程序中不能直接调用。 新车出厂的时候,通过构造函数来初始化其颜色、排量、出厂日期。 class Car {…… public Car() //构造函数 { color=“gray”;//设置新Car对象的颜色 displacement=2.0;//设置排量 Releasedate=DateTime.today;//设置出厂日期 }

构造函数(续) 构造函数不返回值 可以编写有参数的构造函数,让它根据参数来初始 化类的字段 构造函数在创建类的对象时,通过new来调用 public Car() //无参数的构造函数 { color=“gray”;//设置新Car对象的颜色 displacement=2.0;//设置排量 Releasedate=DateTime.today;//设置出厂日期 } public Car(string Color,float Diaplacement) //有参数的构造函数 color=Color;//设置新Car对象的颜色 displacement= Diaplacement;//设置排量 构造函数不返回值 可以编写有参数的构造函数,让它根据参数来初始 化类的字段 构造函数在创建类的对象时,通过new来调用 car1:gray,2.0 Car2:red,2.4 Car car1 = new Car(); //调用无参数的构造函数 Car car2 = new Car(“red”,”2.4”) //调用有参数的构造函数

继承和派生 基类(父类)派生类(子类) 后一代“继承”前一代的 功能 但是在功能上又有所发展 旧电视派生出新电视 新电视继承了旧电视 派生 定时开机 自动搜索

6.3.1 基类和派生类 派生类是基类的一个子集 定义:在已有类的基础上构造新的类, 新类继承了原有类的数据成员、属性、方法和事件 原有的类称为基类,新类称为派生类 派生类是基类的一个子集 面向对象程序设计中的继承性 派生类 派生 继承 基类 派生类 基类 注意:箭头方向 Mammal 哺乳动物 Horse 马 Whale 鲸鱼 Mammal 哺乳动物 基类 派生类

哺乳动物的继承关系 class 派生类名 : 基类名 { //… } 马 鲸鱼 齿鲸 须鲸 豹子 System.Object类是所有类的基类,所有类都隐式派生于Object类。C#编译器会悄悄将Mammal类写为以下代码 class Mammal : Object { //… } C#中定义的所有类会自动继承Object类的特性,如ToString()方法

public void SuckleYoung() //哺乳 class Mammal { public void Breath()//呼吸 … } public void SuckleYoung() //哺乳 class Horse : Mammal { public void Trot() //小跑 … } class Whale: Mammal { public void Swim ()//游泳 … }

派生类的对象 派生类的对象可以作为基类的对象处理 例 定义的派生类对象可以访问基类的公用成员 允许将派生类对象赋值给基类对象 子类调用父类的非私有成员 派生类的对象 class Mammal { public string name; public void Breath() Console.WriteLine(name + "正在呼吸"); } public void SuckleYoung() Console.WriteLine(name + "正在哺乳"); static void Main(string[] args) { Mammal mammal = new Mammal(); mammal.name=“mammal”; mammal.Breath(); mammal.SuckleYoung(); Horse horse = new Horse(); horse.name=“horse”; horse.SuckleYoung(); horse.Trot(); } 派生类的对象可以作为基类的对象处理 定义的派生类对象可以访问基类的公用成员 允许将派生类对象赋值给基类对象 例 class Horse : Mammal { public void Trot() this.Breath();//调用父类的public方法 Console.WriteLine(name + "正在奔跑"); //调用父类的public数据成员 }

无参数构造函数 在建立派生类的实例对象时,先调用基类的构造函 数,再执行派生类的构造函数。 例 class Mammal { public Mammal() Console.WriteLine("我是一只哺乳动物"); } //… static void Main(string[] args) { Horse horse = new Horse(); } 在建立派生类的实例对象时,先调用基类的构造函 数,再执行派生类的构造函数。 例 class Horse : Mammal { public Horse() Console.WriteLine("我是一匹马"); } //…

有参数构造函数 : base(基类构造函数参数表) 用base关键字来指定调用一个基类的构造函数。 先调用基类的有参数构造函数; public 派生类名(派生类构造函数总参数表) : base(基类构造函数参数表) { 派生类数据成员初始化 } 例 用base关键字来指定调用一个基类的构造函数。 先调用基类的有参数构造函数; 然后调用派生类的有参数构造函数

Console.WriteLine("我是一只哺乳动物"); } public Mammal(string mammalName) static void Main(string[] args) { Mammal mammal = new Mammal("mammal"); Horse horse = new Horse("horse"); Console.ReadLine(); } class Mammal { private string name; public Mammal() Console.WriteLine("我是一只哺乳动物"); } public Mammal(string mammalName) name = mammalName; Console.WriteLine(mammalName +"是一只哺乳动物"); class Horse : Mammal { public Horse(string name): base(name) Console.WriteLine(name+"是一匹马"); } //…

例 6.2 定义一个学生类Student 学号 私有 数据成员 姓名 成绩 设置数据成员值 公有 方法 输出数据成员值

自行定义类的事件 引发(或发送)事件的类:“发行者”(生产者) 处理(或接收)事件的类:“订户”(消费者) 事件:类/对象向其他类/对象通知 嘀嘀 在类外声明委托 public delegate void 委托; 在类定义中: 用public Event 委托 事件名 语句声明事件 合适地方引发 事件名() 语句引发事件 在对象实例化时: 对象.事件名+=new 委托(处理方法)添加事件 处理方法代码编写 事件:类/对象向其他类/对象通知 发生的相关事情 Form1_Click事件是如何定义的? Form1_Click事件应用 例6.10 设置学生的成绩,当<60时引发事件 引发(或发送)事件的类:“发行者”(生产者) 处理(或接收)事件的类:“订户”(消费者)

事件 委托除了用于“回调”,最大的用处是支持事件机制 嘀嘀 public Form1() { this.Click += new EventHandler(this.Form_C); } //自编写方法 private void Form_C (object sender, EventArgs e) MessageBox.Show("您在窗体上单击了鼠标"); 类Form1在构造函数中,为事件Click添加了一个处理程序Form1_C ()。 “+=“ 作为委托串联运算符 把一个方法指派给一个委托,使得调用这个委托就相当于调用这个方法。

一个委托可以被指派给多个方法 一个事件就可以同时拥有多个处理程序 两个方法的调用顺序就是它们被指派给Click事件的顺序。 public Form1() { this.Click += new EventHandler(this.Form_Click); this.Click += new EventHandler(this.Form_Click2); } private void Form_Click(object sender, EventArgs e) MessageBox.Show("您在窗体上单击了鼠标"); private void Form_Click2(object sender, EventArgs e) MessageBox.Show("Form_Click2的响应"); 两个方法的调用顺序就是它们被指派给Click事件的顺序。 构造函数为对象的Click事件指定了两个事件处理程序

移除委托 C#允许使用+=运算符来进行委托串联; 也允许使用-=运算符来移除委托。 public Form1() { EventHandler eh = new EventHandler(this.Form_Click); this.Click += eh; this.Click += new EventHandler(this.Form_Click2); this.Click -= eh; }

public delegate void FailHandler() ; public event FailHandler Fail ; 在命名空间内: 关键字:委托 声明一个委托的实例,命名为FailHandler 声明一个委托实例(定义一个委托类型) public delegate void FailHandler() ; 在事件生产者处: 委托名 在事件消费者处: 事件名 订阅事件 在类中声明这个事件(即产生委托的一个实例) 订阅或取消事件 s.Fail += new FailHandler(Fail_Handler); public event FailHandler Fail ; 在合适的地方加入引发事件的代码 编写执行事件的代码 订阅后,只要事件Fail被触发,就会调用Fail_Handler Public static void Fail_Handler() { Console.Write(“不及格”); } public int 成绩 { get { return Score; } set { Score=value; if(Score<60)Fail(); } }

(1)创建应用程序,添加类Student class Student { private string No; // 学号 private string Name; // 姓名 private int Score; // 成绩 public void SetValue(string a, string b, int c) // SetValue方法用于设置各数据成员的值 { No = a; Name = b; Score = c; } public void Print() // Print方法用于输出各数据成员的值 { Console.WriteLine(No); Console.WriteLine(Name); Console.WriteLine(Score); public string 学号 // 定义学号属性 { get { return No; } set { No = value; } public string 姓名 // 定义姓名属性 { get { return Name; } set { Name = value; }

(2)声明事件处理委托 namespace T6._10 { public delegate void FailHandler(); //其他语句 }

(3)在类Student的定义中 声明事件类型 编写引发事件的代码 class Student { //。。。。。。其他语句 public event FailHandler Fail; //声明事件Fail为FailHandler类型 public int 成绩 // 定义成绩属性 get { return Score; } set Score = value; if (Score < 60) Fail(); // 当成绩小于60分时引发Fail事件 }

(4)在类Program中 订阅事件 编写执行事件的代码 class Program { static void Main(string[] args) Student s = new Student(); s.Fail += new FailHandler(Fail_Handler); s.学号 = "9803"; s.姓名 = "王涛"; s.成绩 = 56; } public static void Fail_Handler() Console.WriteLine("不及格");

事件的本质是委托 在类中加入事件: 定义一个委托类型 在类中加入这个委托的一个实例(即事件) 在合适的地方加入对这个委托的调用(触发事 件)

6.4 综合应用 例6.15 定义一个时间类Date,包含年、月、日三 个数据成员,以及一个求第二天日期的方法和输出 日期的方法。

综合应用(续) 例6.16 定义一个汽车类vehicle,其数据成员有车 轮个数wheels和车重weight;再定义一个派生类 —卡车类truck,包含新的数据成员载重量payload 及成员函数载重效率。每个类都有相关数据的输出 方法。 其中:载重效率=载重量/(载重量+车重)