面向对象程序设计学什么

面向对象程序设计学什么,第1张

面向对象程序设计中的概念主要包括:对象、类、数据抽象、继承、动态绑定、数据封装、多态性、消息传递。

面向对象程序设计的三大特征是多态(Polymorphism)、继承(Inheritance)、封装(Encapsulation)。

1、多态

多态核心的思想就是,父类的引用能够指向子类的对象,或者接口类型的引用能够指向实现该接口的类的实例。多态会这样的原因是因为子类就是父类。

2、继承

Java是单继承的,这一点和C++有所不同,这也就意味着,一个类只能继承于一个类,被继承的类叫父类,或者是叫基类baseclass,继承的类叫子类。

Java当中的继承使用关键字extends。可是,一个类能够实现多个接口,多个接口之间用逗号进行分割。实现接口使用关键字implements。

3、封装(Encapsulation)

封装比较的简单,类包含了方法和数据,将方法和数据放在一个类当中,就构成了封装。封装的优点:将变化隔离,便于使用,提高重用性,提高安全性;封装的缺点:将变量等使用private修饰,或者封装进方法内,使其不能直接被访问,增加了访问步骤与难度!

面向对象程序设计的六大基本原则:

1、单一职责原则

不要存在多于一个导致类变更的原因,即一个类只承担一个职责。

2、开放-封闭原则

对扩展开放,对修改封闭。无论模块多么封闭,都会存在一些无法对之封闭的变化,既然不能完全封闭,我们必须对于自己设计的模块应该对哪种变化封闭做出选择,必须先猜测出最有可能发生的变化种类,然后构造抽象来隔离这些变化。

3、迪米特原则

一个对象应该对其他对象有最少的了解,减少类与类之间的耦合。如果两个类不必彼此通信,那么这两个类就不应当发生直接的相互作用。类与类之间的耦合越弱,越有利于复用,一个处于弱耦合的类被修改,不会对有关系的类造成波及。

4、依赖倒转原则

上层模块不要依赖底层模块,它们都要依赖于抽象。抽象不能依赖于细节,细节要依赖于抽象。面向接口编程,不要面向实现编程。

5、里氏替换原则

子类型必须能够替换掉它们的父类型。只有当子类可以替换掉父类,软件单位的功能不受影响时,父类才能真正的被复用,而子类也能够在父类的基础上增加新的行为。

6、接口隔离原则

客户端不应该依赖于它不需要的接口,一个类对一个类的依赖应该建立在最小的接口上。不要让与自己无关的修改影响到自己功能模块的变化。

进入之后选APPWIZARD就可以了,再输入类等参数

面向对象程序设计中的概念主要包括:对象、类、数据抽象、继承、动态绑定、数据封装、多态性、消息传递。通过这些概念面向对象的思想得到了具体的体现。 1)对象 对象是运行期的基本实体,它是一个封装了数据和 *** 作这些数据的代码的逻辑实体。 2)类 类是具有相同类型的对象的抽象。一个对象所包含的所有数据和代码可以通过类来构造。 3)封装 封装是将数据和代码捆绑到一起,避免了外界的干扰和不确定性。对象的某些数据和代码可以是私有的,不能被外界访问,以此实现对数据和代码不同级别的访问权限。 4)继承 继承是让某个类型的对象获得另一个类型的对象的特征。通过继承可以实现代码的重用:从已存在的类派生出的一个新类将自动具有原来那个类的特性,同时,它还可以拥有自己的新特性。 5)多态 多态是指不同事物具有不同表现形式的能力。多态机制使具有不同内部结构的对象可以共享相同的外部接口,通过这种方式减少代码的复杂度。 6)动态绑定 绑定指的是将一个过程调用与相应代码链接起来的行为。动态绑定是指与给定的过程调用相关联的代码只有在运行期才可知的一种绑定,它是多态实现的具体形式。 7)消息传递 对象之间需要相互沟通,沟通的途径就是对象之间收发信息。消息内容包括接收消息的对象的标识,需要调用的函数的标识,以及必要的信息。消息传递的概念使得对现实世界的描述更容易。

面向对象三大特性:封装,继承,多态

面向对象(Object Oriented,缩写为OO)是现代软件技术的精髓。从早期的SmallTalk到如日中天的Java,都渗透着面向对象思想。

OO具有三大特性:封装性、继承性和多态性。想掌握面向对象思想,就必须深入理解

其三大特性。这里我尽量少谈概念,只用一个生活中的例子和一段代码来解释它们。

1、封装性(Encapsulation)

所谓封装,就是将某些东西包装和隐藏起来,让外界无法直接使用,只能通过某些特定的方式才能访问。OO将万物都视为“对象”(Object),任何对象都具有特性和行为。我们将其特性称为“成员变量” (MemberVarible),将其行为称之为“成员函数"(Member Function),被封装的特性只能通过特定的行为去访问。

大家都见过旅馆里常用的一种茶叶吧,就是用纸袋把茶叶包装起来再系是一根线。用的时候只需要将其放在水杯里泡就行。这样的好处是不会将茶叶渣和茶垢弄的满杯子都是。

好!这就是一个封装的例子。

我们喝茶的目的是享受茶叶的香冽;所以茶叶的味道(Flavour)就是茶叶所具有的最

重要特性之一;可是我们无法直接享受它的清香,因为被外面的纸袋“封装”起来了。唯一的办法就是“泡”(Dilute),将茶袋扔在开水中泡,它的味道就出来了,融入水中。

如果我们把袋装茶叶看作一个对象的话,它提供了成员变量Flavour和成员函数Dilute

。并且Flavour是私有(Private)的,我们不能直接把它吞进肚子去,而只能通过成员函

数Dilute才能享受Flavour。

下面用C++代码来描述这个例子:

Class CTea

{

Private:

Cstring m_Flavour//味道

Cstring m_Color //颜色

...... //等等其它属性

Private:

Void CTea() //构造函数

Void ~CTea()//析构函数

Public:

Cstring Dilute()//沏茶

...... //等等其它方法

}

Cstring CTea::Dilute()

{

//怎样泡出味道来的代码

}

这就是封装。通过将对象的某些属性声明为Private隐藏起来,只能使用其提供的特定

方法去访问。

2、继承(Inheritance)

如果只是封装,那么非面向对象语言也能部分的做到。比如在C中,用结构(Struct)、

VB中用自定义类型(Type)也能封装一些变量。

OO最有吸引力的特性是继承。通俗的说后代具有祖先的某些特点就叫继承,当然后代还可以具有自己独有的特征。举个例子吧,菜刀。

菜刀(cutlery)是钢(Steel)做的,钢是一种金属(Metal),金属则是大千世界里的一种物质(Substance)。所以菜刀的一些特性可以追溯到物质具有的一般属性。正是因为这个道理,MFC中所有类均从CObject继承而来。

这就是继承。菜刀直接继承了钢的特性,钢又继承了金属的特性,......下面的代码描

述了这种复杂而有独特的继承关系:

Class CSubstance

{

Private:

int m_color

void CSubstance()

void ~CSubstance()

//......(我是学文科的,具体属性说不上来)

}

Class CMetal:Public CSubstance

{

void CMetal()

void ~CMetal()

//......

}

Class CSteel:Public CMetal

{

void CSteel()

void ~CSteel()

//......

}

Class CCutlery:Public CSteel

{

private:

Cstring m_Blade

void CCutlery()

void ~CCutlery()

//......

Public:

void Cut()

}

这里,CSubstance被称为基类(Base class),其它被称为衍生类(Derived class)。衍生类与基类是“Is kind of”的关系。子类与其祖先类之间复杂的函数调用关系不在本文讨论之列。

继承是一种树状的层次关系。子类在继承祖先类的成员变量和成员函数的同时也可以

定义自己的成员变量和成员函数。比如,Metal 除了继承了Substance的一般特性外,还具有自己的属性诸如可延展性;CCutlery在继承CSteel的特性后还具有自己的成员诸如“刀刃”(Blade)、“锋利”(Sharpness)、行为有如“切”(Cut)等。

面向对象技术是对现实生活的抽象,你可以用生活中的经验去思考程序设计的逻辑。

3、多态性(Polymorphism)

讨论多态之前先要明白什么是“虚拟”(Virtual)。C++/MFC就是用虚拟这种方式实现多态的。为什么“虚拟”这个概念?看下边的例子:

Class Cincect //昆虫类

{

private:

int m_foot //脚的数量

...... //其它成员变量

private:

void Cincect()

void ~Cincect()

public:

void Bite()//咬人

{

......//怎样咬人的代码,比如张开嘴啃

}

}

我把Bite(咬)这个动作在基类中定义为一般化动作。可是,不是所有昆虫咬

人的方法都一样(况且还有的根本就不咬人呢,比如蜻蜓),比如蚊子是用嘴那个

吸管叮人而蚂蚁是用嘴去夹。

从昆虫这个类别衍生出以下两个类别:Cant(蚂蚁)、Cmosquito(蚊子)。

class Cant :public Cincect //蚂蚁类

{

......

}

class Cmosquito :public Cincect //蚊子类

{

......

}

它们都继承了Cincect的所有成员,当然也继承了Bite()这个动作。现在就有问题了:

同样继承自昆虫,当我们使用Bite()这个动作时怎么才能区分蚂蚁和蚊子各自的独有的咬人方式呢?

方法之一是用“::”符号指明具体引用的是那一个,但这样明显失去了灵活性;

另一种方法就是“虚拟”。使用关键字virtual将Bite()声明为虚拟函数,然后在每个

衍生类中重新定义,描述它们各自的咬人方法,调用的时候也不会都一种结果啦。于是上边的例子可以改写为:

Class Cincect //昆虫类

{

private:

int m_foot //脚的数量

...... //其它成员变量

private:

void Cincect()

void ~Cincect()

public:

virtual Bite(){}//咬人,但我们只声明这个成员函数,

//却让它什么动作都不做,让衍生类自己去定

//义各自的咬人方法

}

class Cant :public Cincect //蚂蚁类

{

......

virtual Bite()

}

Cant::Bite()

{

...... //蚂蚁具体的咬人方式

}

class Cmosquito :public Cincect //蚊子类

{

......

virtual Bite()

}

Cmosquito::Bite()

{

...... //蚊子具体的咬人方式

}

所以,虚拟的目的是只在基类中将一般化动作声明一个成员函数的原型而不做

具体定义,让衍生类自己去定义。

这就是面向对象的特征之三:多态性。基类的同一个成员在不同的衍生类中可以具

有不同的形态,更好地抽象和描述大千世界中的诸多“对象”。

1.了解什么是多态性

2.如何定义一个虚方法

3.如何重载一个虚方法

4.如何在程序中运用多态性

面向对象程序设计中的另外一个重要概念是多态性。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。 可以把一组对象放到一个数组中,然后调用它们的方法,在这种场合下,多态性作用就体现出来了,这些对象不必是相同类型的对象。当然,如果它们都继承自某个类,你可以把这些派生类,都放到一个数组中。 如果这些对象都有同名方法,就可以调用每个对象的同名方法。本节课将向你介绍如何完成这些事情。

1.清单9-1. 带有虚方法的基类:DrawingObject.cs

using System

public class DrawingObject

{

public virtual void Draw()

{

Console.WriteLine("I'm just a generic drawing object.")

}

}

说明

清单9-1 定义了DrawingObject类。这是个可以让其他对象继承的基类。该类有一个名为Draw()的方法。Draw()方法带有一个virtual修饰符,该修饰符表明:该基类的派生类可以重载该方法。DrawingObject类的 Draw()方法完成如下事情:输出语句"I'm just a generic drawing object."到控制台。

2.清单9-2. 带有重载方法的派生类:Line.cs, Circle.cs, and Square.cs

using System

public class Line : DrawingObject

{

public override void Draw()

{

Console.WriteLine("I'm a Line.")

}

}

public class Circle : DrawingObject

{

public override void Draw()

{

Console.WriteLine("I'm a Circle.")

}

}

public class Square : DrawingObject

{

public override void Draw()

{

Console.WriteLine("I'm a Square.")

}

}

说明

清单9-2定义了三个类。这三个类都派生自DrawingObject类。每个类都有一个同名Draw()方法,这些Draw()方法中的每一个都有一个重载修饰符。重载修饰符可让该方法在运行时重载其基类的虚方法,实现这个功能的条件是:通过基类类型的指针变量来引用该类。

3.清单9-3. 实现多态性的程序:DrawDemo.cs

using System

public class DrawDemo

{

public static int Main(string[] args)

{

DrawingObject[] dObj = new DrawingObject[4]

dObj[0] = new Line()

dObj[1] = new Circle()

dObj[2] = new Square()

dObj[3] = new DrawingObject()

foreach (DrawingObject drawObj in dObj)

{

drawObj.Draw()

}

return 0

}

}

说明

清单9-3演示了多态性的实现,该程序使用了在清单 9-1 和清单9-2中定义的类。在DrawDemo类中的Main()方法中,创建了一个数组, 数组元素是DrawingObject 类的对象。该数组名为dObj,是由四个DrawingObject类型的对象组成。

接下来, 初始化dObj数组, 由于Line, Circle和Square类都是DrawingObject类的派生类,所以这些类可以作为dObj数组元素的类型。 如果C#没有这种功能,你得为每个类创建一个数组。继承的性质可以让派生对象当作基类成员一样用,这样就节省了编程工作量。

一旦数组初始化之后,接着是执行foreach循环,寻找数组中的每个元素。在每次循环中, dObj 数组的每个元素(对象)调用其Draw()方法。多态性体现在:在运行时,各自调用每个对象的Draw()方法。尽管dObj 数组中的引用对象类型是DrawingObject,这并不影响派生类重载DrawingObject 类的虚方法Draw()。 在dObj 数组中,通过指向DrawingObject 基类的指针来调用派生类中的重载的Draw()方法。

输出结果是:

I'm a Line.

I'm a Circle.

I'm a Square.

I'm just a generic drawing object.

在DrawDemo 程序中,调用了每个派生类的重载的Draw()方法。 最后一行中,执行的是DrawingObject类的虚方法Draw()。这是因为运行到最后,数组的第四个元素是DrawingObject类的对象。

小结

现在对多态性有所了解之后,你可以在派生类中,实现一个重载基类虚方法的方法。虚方法和重载的派生类方法之间的关系就体现出C#的多态性。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7863266.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-10
下一篇 2023-04-10

发表评论

登录后才能评论

评论列表(0条)

保存