面向对象的方法
面向对象编程模式如图所示,在这种模式中,函数和它需要存取的数据封装在称为对象的包中。对象之间的数据访问是间接的,是通过接口进行的。我们可以将对象看做是鸡蛋,蛋黄是数据;蛋清是访问数据的函数;蛋壳代表接口(即那些公开或公布的方法和属性)。蛋壳接口隐匿了函数和数据结构的实现。当数据结构和内部函数变化时,这种变化被限制在内部的局部范围内。由于接口的相对稳定性,使得这种内部变化的影响不会波及到其他对象,除非蛋壳破裂(接口发生变化),因而面向对象模式开发的程序是易于维护和扩展的。对象是被定义为一个封装了状态(数据)和行为(操作)的实体。

- 在面向流程编程模式的过程是:现实世界→面向过程建模(流程图、变量、函数)→面向过程语言→执行求解
- 在面向对象编程模式的过程是:现实世界→面向对象建模(类图、对象、方法)→面向对象语言→执行求解
面向对象、面向过程
面向过程:强调的是功能行为(方法、函数),C语言就是面向过程语言
面向对象:将功能封装进对象,强调具各了功能的对象。
类和对象关系
类就是将某一类事物中所有的共同点抽离出来,形成一个模板,我们在编程中对象是按照模板生产(制造)出来的一个具体的事物
类和类之间的关系
抽象:将同类事物向上抽取的过程
派生(继承):我们编程中的继承指的是类和类之间的关系,称为派生更合适:纲、门、界、数
封装:将不必要暴露的细节隐藏起来
多态,一类事物以多种形态存在
面向对象的特点主要概括为抽象性、继承性、封装性和多态性:
继承性——新的对象类由继承原有对象类的某些特性或全部特性而产生出来,原有对象类称为基类(或称超类),新的对象类称为派生类(或子类,在本书中统一称为派生类),派生类可以直接继承基类的共性,又允许派生类发展自己的个性。继承性简化了对新的对象类的设计。
封装性——指对象的使用者通过预先定义的接口关联到某一对象的服务和数据时,无需知道这些服务是如何实现的。即用户使用对象时无需知道对象内部的运行细节。这样,以前所开发的系统中已使用的对象能够在新系统中重新采用,这就减少了新系统中分析、设计和编程的工作量。
多态性——指不同类型的对象可以对相同的激励做出适当的不同响应的能力。多态性丰富了对象的内容,扩大了对象的适应性,改变了对象单一继承关系。
构造与析构
constructor
声明或定义一个构造函数,可以用于类类型、对象类型、结构类型。当类被实例化时,首先调用此函数,构造函数一般用Create表示,Create方法能够连带类中存在的CreateWnd方法。开始部分使用inheritcd保留字来调用父类的构造函数,单独用inherited:就是继承父类的同名同参数方法,即不带参数就是默认调用同名函数
destructor
声明或定义一个析构函数,可以用于类类型、对象类型。析构函数主要用来释放对象资源。析构函数只允许覆盖,不允许重载。在类被释放时自动调用,析构函数通常用Destroy作为函数名
(1)创建对象
在使用一个对象之前,用class关键字声明一个对象。可以在一个程序或单元的type部分声明一个对象类型:
type
TFooObject = class;
Delphi中的惯例是类型名称以T开头,如TObject,这仅仅是一个惯例
Delphi的对象至少有一个构造器称为create(),调用构造器的语法如下
FooObject:= TFooObject.Create;
(2)销毁对象
当用完对象,应该调用这个实例的Free()方法来释放它。Free()首选进行检查保证这个对象实例不为NIL,然后调用对象的析构方法Destroy()。
FooObject.free;
(3)创建方法
创建一个方法用两个步骤,首先在对象类型的声明中声明这个方法,然后再用代码定义方法
type
TBoogieNights = class
Dance: Boolean;
Procedure DoTheHustle;
end;
procedure TBoogieNights.DoTheHustle;
begin
Dance:= True;
end;
(4)方法的类型
对象的方法能定义成静态(static)、虚拟(virtual)、动态(dynamic)或者消息处理(message)。请看下面的例子
TFoo = class
procedure IAmAStatic;
procedure IAmAVirtual; virtual;
procedure IAmADynamic; dynamic;
//抽象方法是一种在声明它的类中暂时没有实现,而由它的派生类来实现的虚方法或动态方法。声明抽象方法时,必须在virtual或dynamic后而使用限定符。
procedure DoSomething; virtual;abstract;
procedure IAmAMessage(var m: TMessage); message wm_SomeMessage;
end;
(5)方法的覆盖
覆盖一个方法,在派生类的声明中用override代替virtual或dynamic
type
TMan = class (TObject)
public
function SayHello:string;virtual
end;
TChinese = class (TMan)
public
function SayHello;string override;
end;
TAmerican = class (TMan)
public
function SayHello:string override;
end;
implementation
var
AMan:TMan;
begin
AMan:= TChinese.creat;
edit1.text:= AMan.SayHello; //调用的是 TChinese.SayHello
AMan.free;
AMan:= TAmerican.create;
edit1.text:=AMan.SayHello; //调用的是TAmerican.SayHello
AMan.free;
end;
(6)方法的重载
就像普通的过程和函数,方法也支持重载
type
TSomeClass = class
procedure AMethod(I: Integer); overload;
procedure AMethod(S: String); overload;
procedure AMethod(D: Double); overload;
end;
(7)重新引入方法
有时候,需要在派生类中增加一个方法,而这个方法的名称与祖先类中的某个方法名称相同。在这种情况下,没必要覆盖这个方法,只要在派生类中重新声明这个方法,直接在派生类中使用reintroduce指示符
type
TSomeBase = class
procedure Cooper;
end;
TSomeClass = class(TSomeBase)
procedure Cooper; reintroduce;
end;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?