02设计模式面向对象基础.ppt_第1页
02设计模式面向对象基础.ppt_第2页
02设计模式面向对象基础.ppt_第3页
02设计模式面向对象基础.ppt_第4页
02设计模式面向对象基础.ppt_第5页
已阅读5页,还剩92页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、设计模式(Design Pattern),张凯 副教授 计算机学院 软件工程系,主要内容,泛型、委托、事件,5,面向对象基础,简单例子 面向对象编程,Object-Oriented Programming,简单的说针对对象进行编程。 用Visual Studio中建立一个Windows应用程序,点击一个猫叫按钮,会弹出小猫的叫声“喵”的提示框。,面向对象基础,简单例子,private void button1_Click(object sender, EventArgs e) MessageBox.Show(喵); ,让小猫如果多叫几声,怎么办?,面向对象基础,简单例子,private voi

2、d button1_Click(object sender, EventArgs e) MessageBox.Show(喵); MessageBox.Show(喵); MessageBox.Show(喵); MessageBox.Show(喵); MessageBox.Show(喵); MessageBox.Show(喵); MessageBox.Show(喵); MessageBox.Show(喵); ,如果小猫的叫声修改为“喵呜”,怎么办?,这样的设计好不好,为什么?,面向对象基础,简单例子,private void button1_Click(object sender, EventAr

3、gs e) for (int i = 0; i 6; i+) MessageBox.Show( Shout() ); string Shout() return 喵呜; ,如果需要添加一个窗体,也有小猫叫,怎么办?,面向对象基础,简单例子,public static string Shout() return 喵呜; ,private void button1_Click(object sender, EventArgs e) MessageBox.Show( Form1.Shout(); ,Form2,Form1,面向对象基础,面向对象基础,简单例子,public static string

4、 Shout() return 喵呜; ,private void button1_Click(object sender, EventArgs e) MessageBox.Show( Form1.Shout(); ,Form2,Form1,为什么写在Form1里,写在Form2行不行?,究竟写在哪里最正确?,面向对象基础,类与实例 这个猫叫函数应该放在一个更合适的地方,这就是类。 类就是具有相同的属性和功能的对象的抽象的集合。 class就是表示类的关键字,Cat就是类的名称,Shout就是类的方法。,class Cat public string Shout() return 喵; ,如何

5、使用这个类呢?,面向对象基础,类与实例 实例,就是一个真实的对象。比如我们都是“人”,而你和我都是“人” 类的实例。 实例化就是创建对象的过程,使用new关键字来创建。,private void button1_Click(object sender, EventArgs e) Cat cat = new Cat(); MessageBox.Show(cat.Shout(); ,面向对象基础,类与实例 Cat实例化后,等同于出生了一只小猫cat,此时就可以让小猫cat.Shout()了。,private void button1_Click(object sender, EventArgs e

6、) Cat cat = new Cat(); MessageBox.Show(cat.Shout(); ,注意:Cat cat = new Cat(); 其实做了两件事 Cat cat; 声明一个Cat的对象,对象名为cat cat = new Cat(); 将此对象实例化,面向对象基础,Allocating Memory for the Data,面向对象基础,构造函数 我们希望出生的小猫有个名字,比如叫“小花”,当小花叫的时候,最好能说“我的名字叫小花,喵” 构造函数,又叫构造方法,其实就是对类进行初始化。构造函数与类同名,没有返回值,也不需要void,在new的时候调用。,private

7、 void button1_Click(object sender, EventArgs e) Cat cat = new Cat(); MessageBox.Show(cat.Shout(); ,面向对象基础,构造函数,class Cat public string Shout() return 喵; ,在类中没有写过构造函数Cat(),怎么可以调用呢?,private void button1_Click(object sender, EventArgs e) Cat cat = new Cat(); MessageBox.Show(cat.Shout(); ,面向对象基础,构造函数 所有

8、类都有构造函数,如果不编码则系统默认生成空的构造函数,若你有定义的构造函数,那么默认的构造函数就失效了。 系统默认生成了很好啊,那我们写构造函数干什么呢? 构造函数是为了对类进行初始化。比如我们希望每个小猫一出生就有姓名,那么就需要写一个带参数的构造函数。,面向对象基础,构造函数,class Cat private string name = ; public Cat(string name) = name; public string Shout() return 我的名字叫 + name + 喵; ,声明Cat类的私有字符串变量name,定义Cat类的构造函数,参数是输

9、入一个字符串,将参数赋值给私有变量name,面向对象基础,构造函数 这样以来,在客户端生成小猫,就必须要给小猫起名字了。,private void button1_Click(object sender, EventArgs e) Cat cat = new Cat(小花); MessageBox.Show(cat.Shout(); ,面向对象基础,方法重载 如果没有起好小猫的名字,实例就创建不了吗?,面向对象基础,方法重载 如果需要不起名字,也要生出小猫,用方法重载 方法重载提供了创建同名的多个方法的能力,但这些方法需使用不同的参数类型。,面向对象基础,class Cat private s

10、tring name = ; public Cat(string name) = name; public Cat() = 无名; public string Shout() return 我的名字叫 + name + 喵; ,将构造函数重载,注意:方法重载,方法名必须相同,参数类型或个数必须有所不同,面向对象基础,方法重载 如果我们觉得小猫叫的次数不固定,希望我让它叫几声,它就叫几声,如何做? 在构造函数里面添加一个叫的次数? 希望实例化以后还可以修改,我们考虑用“属性”!,面向对象基础,属性与修饰符 属性是一个方法或一对方法,但在调用它的代码看来,它

11、是一个字段,即属性适合于以字段的方式使用方法调用的场合。 字段是存储类要满足其设计所需要的数据,字段是与类相关的变量。,面向对象基础,private int shoutNum = 3; public int ShoutNum get return shoutNum; set shoutNum = value; ,声明一个内部字段,注意是private,默认叫的次数为3,ShoutNum属性,注意是public,当中有两个方法; get表示外界调用时可以得到shoutNum的值; Set表示外界可以给内部的shortNum的赋值,面向对象基础,属性与修饰符 public修饰的类成员可以允许其它任

12、何类来访问,俗称公有的。 private表示只允许同一个类中的成员访问,其它类包括它的子类无法访问,俗称私有的。 如果类的成员没有加修饰符,则认为是private的。 通常字段都是private私有的,属性都是public公有的。,面向对象基础,private int shoutNum = 3; public int ShoutNum get return shoutNum; set shoutNum = value; ,属性有两个方法get和set。get访问器返回与声明的属性相同的数据类型,表示的意思是调用时可以得到内部的值或引用;set访问器没有显示设置参数,但它有一个隐式参数,用关键字

13、value表示,它的作用是调用属性时可以给内部的字段或引用赋值。,这又是何苦呢,把字段的修饰符改为public,不就可以对变量又读又写了吗?,面向对象基础,private int shoutNum = 3; public int ShoutNum get return shoutNum; ,private int shoutNum = 3; public int ShoutNum get return shoutNum; set if (value 10) shoutNum = value; else shoutNum = 10; ,去掉了set,表示ShortNum属性是只读的,控制叫声次数

14、,最多只能叫10声,属性与修饰符 有了ShoutNum属性,Shout方法需要改进了,面向对象基础,public string Shout() return 我的名字叫 + name + 喵; ,public string Shout() string result = ; for (int i = 0; i shoutNum; i+) result += 喵 ; return “我的名字叫” + name + “ + result; ,面向对象基础,private void button1_Click(object sender, EventArgs e) Cat cat = new Cat

15、(小咪); cat.ShoutNum = 5; MessageBox.Show(cat.Shout(); ,属性与修饰符 变量私有的叫字段,公有的是属性 对方法而言,同样有私有方法和共有方法 一般无需对外界公开的方法都应该设置其修饰符为private私有,这才有利于封装。,面向对象基础,封装 面向对象的三大特性之一 每个对象都包含它能进行操作所需要的所有信息,这个特性称为封装,因此对象不必依赖于其它对象完成自己的操作。,面向对象基础,封装 封装有很多好处 第一、良好的封装能够减少耦合 我们让Cat和Form1的耦合分离了 第二、类内部的实现可以自由地修改 我们已经对Cat做了很大的改动 第三、

16、类具有清晰的对外接口 就是指定义为public的ShoutNum属性和Shout方法,面向对象基础,现在需要增加一个狗叫的功能,添加一个按钮,点击后会弹出“我的名字叫XX 汪 汪 汪”,如何做?,面向对象基础,class Dog private int shoutNum = 3; public int ShoutNum get return shoutNum; set if (value 10) shoutNum = value; else shoutNum = 10; private string name = ; public Dog(string name) = na

17、me; public Dog() = 无名; public string Shout() string result = ; for (int i = 0; i shoutNum; i+) result += 汪 ; return 我的名字叫 + name + + result; ,面向对象基础,private void button2_Click(object sender, EventArgs e) Dog dog = new Dog(旺财); dog.ShoutNum = 5; MessageBox.Show(dog.Shout(); ,面向对象基础,class Ca

18、t private int shoutNum = 3; public int ShoutNum get return shoutNum; set if (value 10) shoutNum = value; else shoutNum = 10; private string name = ; public Cat(string name) = name; public Cat() = 无名; public string Shout() string result = ; for (int i = 0; i shoutNum; i+) result +

19、= 喵 ; return 我的名字叫 + name + + result; ,class Dog private int shoutNum = 3; public int ShoutNum get return shoutNum; set if (value 10) shoutNum = value; else shoutNum = 10; private string name = ; public Dog(string name) = name; public Dog() = 无名; public string Shout() string resu

20、lt = ; for (int i = 0; i shoutNum; i+) result += 汪 ; return 我的名字叫 + name + + result; ,代码大量重复,我们要用面向对象第二大特性,继承!,继承,面向对象基础,动物,继承 对象继承代表了一种“is-a”的关系,如果两个对象A和B,可以描述为B是A,则表明B可以继承A “猫是动物”,说明猫与动物之间的继承与被继承的关系 继承者是对被继承者的特殊化,因为它除了具备被继承者的特性外,还具备自己独有的个性 “猫”可能拥有抓老鼠,爬树等“动物”不具备的属性,面向对象基础,继承 继承定义了类如何相互关联,共享特性。继承的工作

21、方式是,定义父类和子类,或叫做基类和派生类,其中子类继承父类的所有特性。子类不但继承了父类的所有特性,还可以定义新的特性。,面向对象基础,继承 学习继承记住三句话,如果子类继承于父类 第一、子类拥有父类非private的属性和功能; 第二、子类具有自己的属性和功能,即子类可以扩展父类没有的属性和功能; 第三、子类还可以以自己的方式实现父类的功能(方法重写),面向对象基础,继承 除了private和public外,还有protected表示继承时子类可以对父类有完全访问权。 也就是说,protected修饰的类成员,对子类公开,对其它类不公开。,面向对象基础,继承,面向对象基础,动物,面向对象基

22、础,class Cat private int shoutNum = 3; public int ShoutNum get return shoutNum; set if (value 10) shoutNum = value; else shoutNum = 10; private string name = ; public Cat(string name) = name; public Cat() = 无名; public string Shout() string result = ; for (int i = 0; i shoutNum; i+

23、) result += 喵 ; return 我的名字叫 + name + + result; ,class Dog private int shoutNum = 3; public int ShoutNum get return shoutNum; set if (value 10) shoutNum = value; else shoutNum = 10; private string name = ; public Dog(string name) = name; public Dog() = 无名; public string Shout() s

24、tring result = ; for (int i = 0; i shoutNum; i+) result += 汪 ; return 我的名字叫 + name + + result; ,我们将相同的代码尽量放到动物类中!,面向对象基础,class Animal protected string name = ; public Animal(string name) = name; public Animal() = 无名; protected int shoutNum = 3; public int ShoutNum get return shou

25、tNum; set shoutNum = value; ,面向对象基础,class Cat : Animal public Cat() : base() public Cat(string name) : base(name) public string Shout() string result = ; for (int i = 0; i shoutNum; i+) result += 喵 ; return 我的名字叫 + name + + result; ,class Dog : Animal public Dog() : base() public Dog(string name) :

26、base(name) public string Shout() string result = ; for (int i = 0; i shoutNum; i+) result += 汪 ; return 我的名字叫 + name + + result; ,继承格式就是 子类 : 父类,子类构造函数需要调用父类同样参数类型的构造函数,用base关键字代表父类,有些失望,子类还是有些复杂,没简单到哪里去?,如果添加马、牛、羊等多个类似的类,总共5个类,需要修改起始的叫声次数,继承 不用继承的话,如果修改功能,就必须在所有重复的方法中修改,代码越多,出错的可能性就越大 而继承的优点是,继承使得所

27、有子类公共的部分都放在了父类,使得代码得到了共享,这就避免了重复,另外,继承可使得修改或扩展继承而来的实现都较为容易。,面向对象基础,继承 继承是有缺点的,父类变,则子类不得不变。 继承会破坏包装,父类实现细节暴露给子类,这其实是增大了两个类之间的耦合性。 继承显然是一种类与类之间强耦合的关系。 当两个类之间的关系是“is-a”的关系时考虑用继承 而当两个类之间的关系是“has-a”的关系,不能用继承比如:人有两只手,手不能继承人。,面向对象基础,面向对象基础,private Animal arrayAnimal;,private void button3_Click(object sende

28、r, EventArgs e) arrayAnimal = new Animal5; ,private void button4_Click(object sender, EventArgs e) foreach (Animal item in arrayAnimal) MessageBox.Show(item.Shout(); ,多态 多态表示不同的对象可以执行相同的动作,但要通过它们自己的实现代码来执行。,面向对象基础,多态 国粹京剧子承父业,代代相传。 有一位父亲是有名的艺术家,六个儿子长大成人,模仿父亲惟妙惟肖。有一天,父亲突然发烧,上不了台,但是票已经卖了,退票影响声誉。于是决定让儿

29、子化了妆代父亲表演。,面向对象基础,多态,面向对象基础,多态 第一,子类以父类的身份出现 儿子代表父亲表演,化妆后就以父亲身份出现了。 第二,子类在工作时以自己的方式来实现 儿子模仿得再好,那也是模仿,儿子只能用自己方式表演父亲的作品。 第三,子类以父亲的身份出现时,子类特有的属性和方法不可以使用 儿子有自己的绝活也不能使用。,面向对象基础,多态 虚方法和方法重写 虚方法,为了使子类的实例完全接替来自父类的类成员,父类必须将该成员声明为虚拟的。这是通过在该成员的返回类型之前添加virtual关键字来实现的。 方法重写,子类可以选择使用override关键字,将父类实现替换为它自己的实现,这就是

30、方法重写override,面向对象基础,面向对象基础,class Animal public virtual string Shout() return ; ,class Cat : Animal public Cat() : base() public Cat(string name) : base(name) public override string Shout() string result = ; for (int i = 0; i shoutNum; i+) result += 喵 ; return 我的名字叫 + name + + result; ,class Dog : An

31、imal public Dog() : base() public Dog(string name) : base(name) public override string Shout() string result = ; for (int i = 0; i shoutNum; i+) result += 汪 ; return 我的名字叫 + name + + result; ,父类添加虚方法 (virtual),子类重写该方法 (override),面向对象基础,private Animal arrayAnimal; private void button3_Click(object se

32、nder, EventArgs e) arrayAnimal = new Animal5; arrayAnimal0 = new Cat(小花); arrayAnimal1 = new Dog(阿毛); arrayAnimal2 = new Dog(小黑); arrayAnimal3 = new Cat(娇娇); arrayAnimal4 = new Cat(“小咪); private void button4_Click(object sender, EventArgs e) foreach (Animal item in arrayAnimal) MessageBox.Show(item.

33、Shout(); ,面向对象基础,多态 不同对象可以执行相同的动作,但要通过他们自己的实现代码来执行。 多态的原理是当方法被调用时,无论对象是否被转换为其父类,都只有位于对象继承链最末端的方法实现会被调用。也就是说,虚方法是按照其运行时类型而非编译时类型进行动态绑定调用的。,面向对象基础,面向对象基础,面向对象基础,Virtual and Override Methods,面向对象基础,现在又来了小牛和小羊来报名,如何做?,面向对象基础,面向对象基础,class Cattle : Animal public Cattle() : base() public Cattle(string name

34、) : base(name) public override string Shout() string result = ; for (int i = 0; i shoutNum; i+) result += “哞; return 我的名字叫 + name + + result; ,class Sheep : Animal public Sheep() : base() public Sheep(string name) : base(name) public override string Shout() string result = ; for (int i = 0; i shoutN

35、um; i+) result += “咩 ; return 我的名字叫 + name + + result; ,重构 两个互为兄弟的子类代码类似,并非完全相同 首先采用Extract Method(提炼函数)区分相同部分和差异部分代码,构成单独函数 然后再对提炼的代码使用Pull Up Method(方法上移),将它移入父类,面向对象基础,面向对象基础,class Cattle : Animal public Cattle() : base() public Cattle(string name) : base(name) public override string Shout() stri

36、ng result = ; for (int i = 0; i shoutNum; i+) result += “哞 ; return 我的名字叫 + name + + result; ,class Cattle : Animal public Cattle() : base() public Cattle(string name) : base(name) public override string Shout() string result = ; for (int i = 0; i shoutNum; i+) result += getShoutSound() + “ ; return

37、 我的名字叫 + name + + result; protected string getShoutSound() return 哞; ,面向对象基础,class Animal public string Shout() string result = ; for (int i = 0; i shoutNum; i+) result += getShoutSound() + ,; return 我的名字叫 + name + + result; protected virtual string getShoutSound() return ; ,面向对象基础,class Cat : Anima

38、l public Cat() : base() public Cat(string name):base(name) protected override string getShoutSound() return 喵; ,class Dog : Animal public Dog() : base() public Dog(string name):base(name) protected override string getShoutSound() return 汪; ,抽象类 我们观察发现,Animal类其实根本就不可能实例化 动物是一个抽象名词,没有具体对象与之对应 可以把实例化没有

39、意义的类改成抽象类 同样getShoutSound函数也没有任何意义,可以将virtual修饰符修改为abstract,使之成为抽象方法,面向对象基础,面向对象基础,abstract class Animal protected abstract string getShoutSound(); ,抽象类 第一,抽象类不能实例化 比如动物实例没有实际意义 第二,抽象方法必须是被子类重写的方法 不重写的话,也没有存在意义,看作没有实现体的虚方法 第三,如果类中包含抽象方法,那么类必须定义为抽象类,无论是否包含一些其它方法,面向对象基础,面向对象基础,面向对象基础,这样设计有什么问题?,接口 只有三

40、个特殊动物具备的方法,如何处理? 接口(interface)是把隐式公共方法和属性组合起来,以封装特定功能的一个集合。一旦类实现了接口,类就可以支持接口所指定的所有属性和成员。声明接口在语法上与声明抽象类完全相同,但不允许提供接口中任何成员的执行方式。 一个类可以支持多个接口,多个类也可以支持同一个接口。,面向对象基础,面向对象基础,面向对象基础,interface IChange string ChangeThing(string thing); ,注意:接口用interface声明,而不是class,接口名称前要加 I ,接口中的方法或属性前面不能有修饰符、方法不能有方法体。,面向对象基础

41、,class MachineCat:Cat, IChange public MachineCat() : base() public MachineCat(string name): base(name) public string ChangeThing(string thing) return base.Shout() + 我有万能的口袋,我可变出 + thing; ,面向对象基础,private void button6_Click(object sender, EventArgs e) MachineCat mcat = new MachineCat(叮噹); StoneMonkey

42、wukong = new StoneMonkey(孙悟空); IChange array = new IChange2; array0 = mcat; array1 = wukong; MessageBox.Show(array0.ChangeThing(各种各样的东西!); MessageBox.Show(array1.ChangeThing(各种各样的东西!); ,面向对象基础,接口和抽象类的区别 抽象类可以给出一些成员的实现,接口却不包含成员的实现,抽象类的抽象成员可被子类部分实现,接口的成员需要实现类完全实现,一个类只能继承一个抽象类,但可实现多个接口等。 第一,类是对象的抽象,抽象类

43、是对类的抽象;接口是对行为的抽象。 第二,如果行为跨越不同类的对象,可使用接口;对一些相似的类对象,用继承抽象类。,面向对象基础,接口和抽象类的区别 第三,从设计的角度讲,抽象类是从子类中发现了公共的东西,泛化出了父类,然后子类继承父类,而接口是根本不知子类的存在,方法如何实现还不确认,预先定义的。,面向对象基础,集合(IList接口),面向对象基础,private Animal arrayAnimal; private void button3_Click(object sender, EventArgs e) arrayAnimal = new Animal5; arrayAnimal0

44、= new Cat(小花); arrayAnimal1 = new Dog(阿毛); arrayAnimal2 = new Dog(小黑); arrayAnimal3 = new Cat(娇娇); arrayAnimal4 = new Cat(咪咪); ,插入一个Cat哆啦A梦,参加比赛,集合(IList接口),面向对象基础,集合(IList接口),面向对象基础,private void button6_Click(object sender, EventArgs e) IList AnimalList; AnimalList.Add(new Cat(小花); AnimalList.Add(n

45、ew Dog(阿毛); AnimalList.Add(new Cat(小黑); AnimalList.Add(new Dog(娇娇); AnimalList.Add(new Dog(咪咪); AnimalList.Insert(1,new Cat(哆啦A梦); foreach (Animal item in AnimalList) MessageBox.Show(item.Shout(); ,集合(IList接口),面向对象基础,集合(IList接口),面向对象基础,集合(IList接口),面向对象基础,集合(IList接口),面向对象基础,private void button6_Click

46、(object sender, EventArgs e) IList AnimalList = new ArrayList(); AnimalList.Add(new Cat(小花); AnimalList.Add(new Dog(阿毛); AnimalList.Add(new Cat(小黑); AnimalList.Add(new Dog(娇娇); AnimalList.Add(new Dog(咪咪); AnimalList.Insert(1,new Cat(哆啦A梦); foreach (Animal item in AnimalList) MessageBox.Show(item.Shout(); ,集合(IList接口) ArrayList可以动态的添加、删除、修改、查询,比数组更方便,这是ArrayList的优势。 但是ArrayList也有不足,所有的参数都是Object类型,面向对象基础,private void button6_Click(object sender

温馨提示

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

评论

0/150

提交评论