Download presentation
Presentation is loading. Please wait.
1
C#程序设计 10软件1、2班 王槐彬 计算机工程学院
2
学习目标 理解面向对象的基本概念:对象、类、对象的属性、方法等 创建和使用类 理解类成员的概念,并能够自定义合适的类成员
理解什么是抽象以及如何将现实世界中的实体抽象成类和对象 理解什么是封装以及如何进行有效的封装 面向对象(Object-Oriented,OO)是一种有效的软件开发方法,它将数据和对数据的操作作为一个相互依赖、不可分割的整体,采用数据抽象和信息隐蔽技术,力图更简单的解决现实世界中的问题。是目前最为流行的一种软件开发方法
3
第6讲 面向对象基础 3
4
C# 程序设计 项目1 :认知.NET与 C# 项目2 :数据运算 项目3 :程序流程控制 项目4 :收集同一类型数据
项目5 :堆积木——方法 项目6 :面向对象基础 项目7 :面向对象高级 项目8:调试程序和异常处理 项目9:开发 Windows 窗体应用程序 项目10:开发图形应用程序 项目11:文件流操作 项目12: 数据库访问——ADO.NET 4
5
学习目标 理解面向对象的基本概念:对象、类、对象的属性、方法等 创建和使用类 理解类成员的概念,并能够自定义合适的类成员
理解什么是抽象以及如何将现实世界中的实体抽象成类和对象 理解什么是封装以及如何进行有效的封装 面向对象(Object-Oriented,OO)是一种有效的软件开发方法,它将数据和对数据的操作作为一个相互依赖、不可分割的整体,采用数据抽象和信息隐蔽技术,力图更简单的解决现实世界中的问题。是目前最为流行的一种软件开发方法
6
工作任务:“贪吃蛇”游戏 情景介绍
7
声明类 知识、技能要求 面向对象程序设计 基于Windows的窗体应用程序开发 图形与动画GDI+ 项目资料 设计文档、参考程序 7
8
第6讲 面向对象基础 理解面向对象 面向对象的概念 面向对象程序设计 小结 实验 习题
9
理解面向对象 什么是面向对象?为什么需要面向对象呢?要解决这些问题,我们首先看一个简单的例子。 9
10
理解面向对象(续) 面向对象思想如此考虑: 场景中所有角色抽象起来总共有两类:猫和老鼠 从体型上看,老鼠比较矮小,猫比较高大
老鼠偷吃东西,触发猫捉老鼠 ,老鼠逃跑 将猫和老鼠具体化成“Tom”和“Jerry” “猫捉老鼠”方法 “老鼠逃跑”方法 “老鼠偷吃东西”事件 10
11
理解面向对象(续) 用面向对象的程序实现: 类:抽象出猫类和老鼠类。 属性:定义猫类和老鼠类的“体型”属性 。
方法:定义猫类的“捉老鼠”方法,老鼠类的“逃跑”方法 。 事件:定义“老鼠偷吃东西”事件 。 对象:将猫类实例化成“Tom”对象,老鼠类实例化成“Jerry”对象。 完成场景 。 11
12
理解面向对象——示例 场景: “司令员发号,高个子男人拿起枪射击”
经过合理的抽象后,类是__________,事件是________,属性是_________,方法是__________。 “猫大叫,老鼠逃跑,主人惊醒” 经过合理的抽象后,对象有__________,事件是________,方法是__________。 12
13
理解面向对象——示例 类? 属性? 方法? 豆类 (Bean) 块类 (Block) 蛇类 (Snake) 场地类(Floor)
...... 属性? 方法? 蛇显示方法(Display)、蛇消除方法(UnDisplay)、转向方法(TurnDirection)、蛇生长方法(Growth) 13
14
第6讲 面向对象基础 理解面向对象 面向对象的概念 面向对象程序设计 小结 实验 习题
15
面向对象的概念 对象的概念: 对象是在程序设计中,人们要研究的现实世界中某个具体事物。 ——万物皆对象
16
对象的描述 对象 属性 方法 对象的主要描述包括属性和方法 。 1. 对象的属性是指对象拥有的各种特征,是对象的静态状态。
1. 对象的属性是指对象拥有的各种特征,是对象的静态状态。 2. 对象的方法是指对象能够完成什么动作,是对象的动态行为。 对象 = 属性 + 方法 对象 属性 方法
17
面向对象的概念 类的概念: 类是一组具有相同或相似性质的对象的抽象。 类有属性和方法,它们是一组相似对象状态和行为的抽象。 17
18
类和对象的联系 对象的抽象是类,类的实例化就是对象; 每个对象都是类的实例,对象和对象之间相互独立,互不影响;
属于同个类的对象共享相同的属性名,但属性值可以不同。 Kitty猫的体重是1.5kg,Garfield猫的体重是5kg... 18
19
第6讲 面向对象基础 理解面向对象 面向对象的概念 面向对象程序设计 小结 实验 习题
20
声明类 类是 C# 中功能最为强大的数据类型,使用 class 关键字来定义。 访问修饰符 class 类名 {
//类的成员定义,字段、属性、方法、事件等 } 20
21
访问修饰符 修饰符 说明 public 所属类的成员以及非所属类的成员都可以访问 internal 当前程序集可以访问 private
只有所属类的成员才能访问 protected 所属类或派生自所属类的类才可以访问
22
声明类 示例: public class Cat { private string name; //字段
public string Name //属性 get { return name; } set { name = value; } } public void Catch() //方法 Console.WriteLine(“猫捉老鼠”);
23
创建对象 使用new操作符,将类实例化为对象: 类名 对象名 = new 类名(); 示例: Cat c = new Cat(); 23
24
类成员 字段 属性 索引器 方法 事件
25
字段 “字段”是直接在类中声明的任何类型的变量。 字段使类可以封装数据。 在类中声明字段的方式如下: 访问修饰符 数据类型 字段名;
访问修饰符 数据类型 字段名; 访问对象中的字段: 对象名. 字段名 25
26
字段 示例: public class Cat { public string name; public int age;
public double weight; } 访问对象中的字段: Cat c = new Cat(); c.name = “Tom”; 不推荐使用public ! 26
27
只有 Mouse 类和Cat 类都在同一程序集中,才可访问internal成员
访问修饰符 Mouse类 Cat 类 private 成员 不可访问 protected 成员 不可访问 public 成员 可以访问 只有 Mouse 类和Cat 类都在同一程序集中,才可访问internal成员 internal 成员
28
字段 字段访问级别的设计: 在满足需要的前提下,访问级别尽可能的低 ,最好将所有的字段设计为private的,不推 荐将所有的字段都设置为public的。 类公开的数据应通过方法、属性和索引器提 供。 通过使用这些结构间接访问内部字段, 可以针对无效的输入值提供防护。 28
29
常量 常量是在编译时设置其值并且永远不能更改其值 的字段。声明类的常量时使用const关键字。 示例: class Constants {
private const double Pi = ; private const int SpeedOfLight = ; // km/s } 29
30
属性 属性:提供灵活的机制来读取、编写或计算私有字段的值。
属性使类能够以一种公开的方法获取和设置值: 不直接操作类的数据内容,而是通过访问器进行 访问。其中,get 访问器用于返回属性值,而 set 访问器用于分配新值,新值由value 关键字定义 。 访问修饰符 数据类型 属性名 { get { return 私有字段;} set { 私有字段 = value ; } } 不实现set方法的属性是只读的 30
31
属性 class Cat { private int age; //字段 public int Age //属性
get { return age; } set { //确保Age值大于0 if ( value >0 ) age = value; } class Program static void Main(string[] args) Cat c = new Cat(); c.Age = 2; Console.WriteLine(“猫的年龄是{0}”, c.Age); 将字段标记为私有可确保该字段只能通过调用属性来更改。 31
32
自动实现的属性 当属性访问器中不需要其他逻辑时,自动实现的属性可使属性声明变得更加简洁。 示例: public class Cat {
自动实现的属性必须同时声明 get 和 set 访问器。 示例: public class Cat { public string Name { get; set; } public int Age { get; set; } public double Weight { get; set; } } 32
33
索引器 索引器允许类或结构的实例就像数组一样进行索引。索引器类似于属性,不同之处在于索引器的名称为this关键字,且索引器采用参数。
34
索引器 class DayArray { string[] day = new string[7];
public string this[ int i ] //索引器 get { return day[i]; } set { day[i] = value; } } class Program static void Main(string[] args) DayArray d = new DayArray(); d[0] = "Sun"; Console.WriteLine(d[0]); 将字段标记为私有可确保该字段只能通过调用属性来更改。 34
35
索引器 索引器就是一类特殊的属性 属性 索引器 允许调用方法,如同它们是公共数据成员 允许调用对象上的方法,如同对象是一个数组
可通过简单的名称进行访问 可通过索引器进行访问 可以是静态成员或实例成员 必须是实例成员 属性的 get 访问函数没有参数 索引器的 get 访问函数具有与索引器相同的形参表 属性的 set 访问函数包含隐式 value 参数 除了 value 参数外,索引器的 set 访问函数还具有与索引器相同的形参表
36
方法 方法: 体现对数据的操作,描述对象的行为。 在对象上调用方法: 对象名. 方法(参数列表) 36
37
方法 示例: public class Cat { public void Catch() //方法
Console.WriteLine(“猫捉老鼠”); } class Program static void Main(string[] args) Cat c = new Cat(); c.Catch();
38
构造函数 构造函数是在创建类的对象时执行的类方法。 它通常用于初始化新对象的数据成员。 语法: 访问修饰符 类名 (参数) {
访问修饰符 类名 (参数) { //构造函数函数体 } 构造函数的一些特殊的性质 : 构造函数的名字必须与类同名 构造函数没有返回类型,它可以带参数,也可以不带参数 38
39
构造函数 构造函数(续) 声明类对象时,系统自动调用构造函数,并最先执行构造函数中的语句。构造函数不能被显式调用,一般用于执行类的初始化任务
构造函数可以重载,从而提供初始化类对象的不同方法 若在声明时未定义构造函数,系统会自动生成默认的构造函数,此时构造函数的函数体为空 39
40
构造函数 class Cat { private int n; public Cat() class Program { n=0;
Console.WriteLine(“n赋初值为{0}”,n ); } public Cat(int m) n=m; class Program { static void Main(string[] args) Cat a = new Cat(); Cat b = new Cat(5); } 40
41
析构函数 用于执行清除操作的特殊方法。 当某个类的实例被认为不再需要,在销毁该实例 时,将执行析构函数对资源进行回收。 语法:
~ 类名 ( ) { //析构函数的主体 } 与构造函数相比,析构函数没有参数,不能被重 载,而且没有访问修饰符 41
42
对象和集合初始值设定项 使用对象初始值设定项可以在创建对象时向对象 的任何可访问的字段或属性分配值,而无需显式 调用构造函数。
public class Cat { public string Name { get; set; } public int Age { get; set; } } 实例化 Cat c = new Cat { Name = “Tom”, Age = 2 }; 42
43
对象和集合初始值设定项 使用对象初始值设定项可以在创建对象时向对象 的任何可访问的字段或属性赋值。 class Cat {
public string Name { get; set; } public int Age { get; set; } } 实例化对象后,分别给对象的属性赋值 Cat c = new Cat(); c.Name = "Tom"; c.Age = 2; 在一行语句里完成初始化对象操作 Cat c = new Cat { Name = "Tom", Age =2 }; 43
44
静态成员 静态成员:声明为static的类的成员。 静态成员是属于类所有的,不依赖于特定的对象,可以作为类中“共”有的成员。
静态成员可以直接使用,不必创建对象,不允许通过对象来访问静态成员 非静态成员:没有声明为static的类的成语 非静态成员(实例成员)属于类的实例——对象。 非静态成员只能通过对象访问 静态成员包括字段、属性、方法、事件和构造函数,但不能是索引器、析构函数。 44
45
静态成员 访问方式: 本类内部: 非静态方法可以访问静态成员 静态方法只能访问静态成员 本类外部: 类名. 静态成员 对象名. 非静态成员
45
46
静态成员 class StaticSample { public int x; public static int y;
public void F() x = 1; y = 1; } public static void G() //x = 1; class Program { static void Main() StaticSample t = new StaticSample(); t.x = 1; // 正确 t.y = 1; // 错误, StaticSample.x = 1; // 错误 StaticSample.y = 1; // 正确 } 46
47
this关键字 this仅限于在构造、析构函数、类的方法和类的实例中使用。
48
this关键字 class A { private int x; public A(int x) this.x = x; }
public void PrintX() int x = 5; Console.WriteLine("The value of x is: {0}", x); Console.WriteLine("The value of this.x is: {0}", this.x); public static void Main() A a = new A(10); a.PrintX(); 48
49
委托 理解委托 多播委托
50
理解委托 委托和方法必须具有相同的签名 在运行时确定调用哪种方法 void Multiply(int,int) { …. } ---
void Divide(int,int) --- public delegate void Call(int num1, int num2); 委托是事件的基础。 通过将委托与命名方法或匿名方法关联,可以实例化委托。 在运行的时候,我们才知道该调用哪个方法,在这之前我们只知道方法的返回类型和将要传递给方法的参数,至于哪个方法去执行,我们并不知道,其实我们也不关心,我们关心的是方法执行的结果 委托和方法必须具有相同的签名
51
声明和实例化委托 声明语法 实例化语法 [访问修饰符] delegate 返回类型 委托名(参数列表);
可以看作定义一个类 [访问修饰符] delegate 返回类型 委托名(参数列表); 实例化语法 可以看作类的实例化 委托类型的声明与方法签名相似,有一个返回值和任意数目任意类型的参数 delegate 是一种可用于封装命名或匿名方法的引用类型。 可以将定义委托可以看作是定义一个类 委托名 委托实例名 = new 委托名(方法名称);
52
调用委托 public delegate int Call(int num1, int num2); class Delegates {
static int Multiply(int num1, int num2) return num1 * num2; } static int Divide(int num1, int num2) return num1 / num2; static void Main(string[] args) Call objCall = new Call(Multiply); //Call objCall = Multiply; int result = objCall(5, 3); Console.WriteLine(result); 将方法与委托关联起来 委托实例名称(参数); 变量=委托实例名称(参数);
53
调用委托 //声明委托 public delegate double MathAction(double num);
class DelegateTest { //定义与委托具有相同签名的方法 static double Double(double input) return input * 2; } static void Main(string[] args) //使用命名方法实例化委托 MathAction ma = Double; //调用委托 double two = ma(4.5); Console.WriteLine(two); //使用匿名方法实例化委托 MathAction ma2 = delegate(double input) { return input * input; }; double square = ma2(5); Console.WriteLine(square); //使用lambda表达式实例化委托 MathAction ma3 = s => s * s * s; double cube = ma3(4); Console.WriteLine(cube);
54
多播委托 委托对象支持使用操作符“+”来连接。委托的“+”并非计算两个值的和,而是把方法加入执行队列。 委托第一个方法
委托引用=new 委托名称(方法名称); 第二个以后的方法 委托引用+=new 委托名称(方法名称);
55
多播委托 public delegate void Del(string s); class DelegateTest {
static void Hello(string s) Console.WriteLine(“Hello,{0}“, s); } static void Goodbye(string s) Console.WriteLine(“Goodbye,{0}“, s); static void Main(string[] args) Del a, b, c; a = Hello ; b = Goodbye; c = a + b; //两个委托a和b组合成c c(“C”); //调用委托
56
事件 基于 Windows 的应用程序和 Web 应用程序都是基于事件驱动的应用程序,即根据事件来执行代码。
57
不关心 事件 事件源 事件的发送方 宣布人 集中注意力聆听 未订阅该事件 事件的接收方 “请听题~”
事件的发送方:发送事件的对象,负责引发事件,它本身并不处理事件。 事件的接收方:在事件发生时,被通知的对象,只负责接收和处理事件。 事件发送方并不知道谁将来接收并处理事件,而接收方也不知道什么时候事件将会发送过来 不关心 集中注意力聆听 未订阅该事件 其他人 抢答者 抢答者 事件的接收方
58
事件中的对象分析 如何引发事件 在事件发送方内部,通过调用方法来引发事件。即是,引发事件就是调用一个事件发送方内部的方法
引发事件的方法有什么用? 通知事件接收方接收并处理这个事件。 事件发送方是否知道处理事件对象中的哪个方法去处理事件? 不知道,也不需要知道。 怎样才能做到引发事件后,就有一个事件接收方去处理事件 使用委托,在引发事件的方法中调用委托,调用委托即是调用方法
59
事件中的对象分析 怎么使用委托 在产生事件的对象中包含一个委托对象,当然在这个对象中,我们不知道将使用哪个方法来处理这个事件,没关系,我们可以在这个对象的外部给它添加。 升华 现在为止,我们认为事件仅仅是个委托而已 在类的内部将委托看作一个字段,并使用event关键字将委托声明为一个事件,这样从理解上更明晰了
60
声明事件 (1)声明关于事件的委托 (2)在类中声明事件 [访问修饰符] delegate 返回值类型 委托名(参数列表) ;
委托名建议用EventHandler结尾 [访问修饰符] event 委托名 事件名;
61
引发事件 (3)在类中需要引发事件的方法中,编写引发事件的代码 //引发事件 if ( 事件名 != null )
事件名 ( 参数列表 );
62
事件处理方法 (4)在事件接收方的类中,编写事件处理方法,即与委托签名相同的方法,用于接收方处理事件 //事件处理方法
[访问修饰符] 返回值类型 方法名(参数列表) { //方法实现 }
63
订阅事件 (5)订阅事件,当事件发生时通知接收方处理 //委托对象外部通知订阅事件 或 发送方对象.事件名+= 接收方对象.事件处理方法名;
发送方对象.事件名 += new 委托名(接收方对象.事件处理方法名);
64
事件例子 public delegate void EventHandler(); //事件发送方 class Baby {
public event EventHandler iEvent; public void ill() //引发事件 if (iEvent != null) iEvent(); } //事件接收方 class Father //事件处理方法 public void Care() Console.WriteLine(“照看孩子"); class Program { static void Main(string[] args) Baby b = new Baby(); Father f = new Father(); b.iEvent += f.Care; b.ill(); } 64
65
事件 在.NET Framework类库中,已经定义了很多事件和事件委托,规定了事件发生时事件参数是如何组成的。因此,程序员的主要工作集中在编写事件的处理方法上,来完成应用程序要实现的目标,不必考虑事件是如何实现的。
66
第6讲 面向对象基础 理解面向对象 面向对象的概念 面向对象程序设计 小结 实验 习题
67
小结 本章主要介绍了面向对象的基本概念,面向对象以抽象和封装的方式将事物划分成类,用对象实例化的操作来解决问题。 67
68
面向对象的概念 对象的抽象是类,类的实例化就是对象; 每个对象都是类的实例,对象和对象之间相互独立,互不影响;
每个对象对于每个属性都有自己的值,但与该类的其它对象共享属性名和操作。 68
69
面向对象特性 抽象 封装 继承 多态
70
抽象 抽象的基本概念: 抽象是科学研究中经常使用的一种方法,即去掉被研究对象中与主旨无关的次要部分,或是暂时不考虑的部分,而仅仅抽象出于研究工作有关的实质性的内容并加以研究。 ——抓住西瓜,去掉芝麻 70
71
封装 封装: 1.定义: 封装是指使用抽象数据类型将数据和基于数据的操作包装在一起。 2.目的:封装的主要目的是达到接口和实现的分离。
数据被保护在抽象数据类型的内部,系统的其他部分只有通过包裹在数据外面的被授权的操作,才能与这个抽象数据类型进行交互。
72
类的实现 在开发过程中,类的实现是核心问题。 在以面向对象风格所编写的系统中,所有的数据都 被封装在类的实例中。
73
第6讲 面向对象基础 理解面向对象 面向对象的概念 面向对象程序设计 小结 实验 习题 73
74
实验 参照实验手册,并在教师指导下完成实验报告。 74
75
第6讲 面向对象基础 理解面向对象 面向对象的概念 面向对象程序设计 小结 实验 习题 75
76
习题 1. 填空题 (1) 声明为_________的类成员,只能为定义这些成员的类的方法所访问。
1. 填空题 (1) 声明为_________的类成员,只能为定义这些成员的类的方法所访问。 (2) 关键字_________表示一个类的定义。 (3) 关键字_________表明对象或者变量在初始化后不可修改。 76
77
习题(续) 2. 判断正误,如果错误,请说明原因。 (1) 构造函数可以返回值。 (2) 属性必须同时定义Get()和Set()方法。
2. 判断正误,如果错误,请说明原因。 (1) 构造函数可以返回值。 (2) 属性必须同时定义Get()和Set()方法。 (3) 类的static成员可以通过该类的实例来引用。 (4) this关键字引用的是该对象本身。 77
78
习题(续) 3. 编程题 使用重载构造函数的方法来创建data类,使该类的对象既可以接受一个string类型的数据初始化,也可以接受一个int类型的数据初始化。初始化时将输入的内容打印出来。 78
Similar presentations