【delphi11】delphi进阶【四、面向对象编程(OOP)】

        面向对象编程(OOP)是现代编程中的一个核心概念,尤其在使用像 Delphi 这样的面向对象的语言时。它基于三个主要原则:封装、继承和多态。我们将通过 Delphi 编程语言来探讨这些概念。

目录

类和对象

封装(Encapsulation)

继承(Inheritance)

重写方法

构造和析构

析构函数的注意事项

注意事项

多态(Polymorphism)

使用方法

注意事项

使用技巧

工厂类代码示例

基类和子类

实现工厂类

使用工厂类


类和对象

  1. 类(Class)

    • 类是对象的蓝图或模板。它定义了一组属性(用于存储数据)和方法(用于执行操作)。
    • 在 Delphi 中,类是使用 class 关键字定义的。

        声明一个类

        一个基本的 Delphi 类声明包括属性、方法和构造函数/析构函数的定义。以下是一个简单类的例子:

type
  TPerson = class
  private
    FName: string; // 私有属性
    FAge: Integer;
  public
    constructor Create(Name: string; Age: Integer);
    destructor Destroy; override;
    procedure DisplayInfo; // 公开方法
    property Name: string read FName write FName; // 属性访问器
    property Age: Integer read FAge write FAge;
  end;

         构造函数和析构函数

        构造函数 (constructor) 用于初始化类的新实例。

        析构函数 (destructor) 用于清理在对象销毁时需要释放的资源

 

constructor TPerson.Create(Name: string; Age: Integer);
begin
  FName := Name;
  FAge := Age;
end;

destructor TPerson.Destroy;
begin
  // 清理代码
  inherited;
end;

        方法:

        方法可以是过程(procedure)或函数(function),用于定义类的行为。

procedure TPerson.DisplayInfo;
begin
  ShowMessage('Name: ' + FName + ', Age: ' + IntToStr(FAge));
end;

         

        属性:

        属性是对内部字段的封装,提供了读取(read)和写入(write)的接口。

property Name: string read FName write FName;
property Age: Integer read FAge write FAge;
  1. 对象(Object)

    • 对象是类的实例。当你根据类创建一个实际的实例时,你就创建了一个对象。
    • 在 Delphi 中,对象通常通过调用类的构造函数来创建

封装(Encapsulation)

  • 封装是将数据(属性)和操作该数据的代码(方法)捆绑在一起的做法。
  • 它提供了一种方式来限制对对象内部状态的直接访问,并可以通过公共方法来控制对这些状态的访问。
  • 在 Delphi 中,你可以通过定义 privateprotected 属性和方法来实现封装。

继承(Inheritance)

  • 继承允许一个类(子类)继承另一个类(父类)的特性,如方法和属性。
  • 这意味着你可以创建一个通用的父类,然后创建更专门化的子类。
  • 在 Delphi 中,继承是使用 TObject 类或其他已定义类作为基类来实现的。

        在 Delphi 中,继承是面向对象编程的一个核心概念,它允许一个类(子类)继承另一个类(基类或父类)的属性和方法。这样,子类可以扩展或修改基类的行为。下面我们来详细探讨 Delphi 中继承的写法、高级技巧以及注意事项。

        在 Delphi 中,继承通过在类声明中指定一个基类来实现。子类继承了基类的所有公共(public)、保护(protected)和发布(published)成员。

type
  TAnimal = class
  public
    procedure Speak; virtual;
  end;

  TDog = class(TAnimal)
  public
    procedure Speak; override;
  end;

         在上面的例子中,TDog 类继承自 TAnimal 类。TDog 重写了 Speak 方法,这是多态的一个典型应用。

重写方法

  • 子类可以重写基类中定义为 virtualdynamic 的方法。
  • 使用 override 关键字来指明方法被重写。
procedure TDog.Speak;
begin
  inherited;  // 调用基类的方法
  // 添加额外的功能
end;

构造和析构

constructor TDog.Create;
begin
  inherited Create;
  // 初始化代码
end;

destructor TDog.Destroy;
begin
  // 清理代码
  inherited;
end;

析构函数的注意事项

  1. 调用基类的析构函数:在子类的析构函数中,应调用基类的析构函数,以确保基类的资源得到正确释放。这同样通过 inherited 关键字实现。

  2. 资源释放顺序:首先执行子类的析构函数,然后执行基类的析构函数。

  3. 避免资源泄漏:确保子类的析构函数正确清理所有子类特有的资源。

type
  TDog = class(TAnimal)
  public
    destructor Destroy; override;
  end;

destructor TDog.Destroy;
begin
  // 子类特有的清理代码
  inherited; // 调用基类的析构函数
end;
  • 在 Delphi 中,虽然构造函数和析构函数的命名是自由的,但最常见的习惯是使用 CreateDestroy
  • 当重写构造函数和析构函数时,确保使用 override 关键字。
  • 在构造函数和析构函数中,适当使用 inherited 是非常重要的。这确保了基类的构造函数和析构函数被正确地调用,从而维护了对象的完整性。

通过遵循这些准则,你可以确保在使用 Delphi 进行面向对象编程时,对象的生命周期得到正确的管理。这对于编写可靠、稳定的应用程序至关重要。

注意事项

  • 方法重写:确保使用 override 关键字重写基类中的 virtualdynamic 方法。
  • 调用 inherited:在重写方法时,适当地使用 inherited 调用基类实现。
  • 构造函数和析构函数:正确管理构造函数和析构函数的继承,特别是在涉及资源管理时。
  • 类型兼容性:子类的实例可以赋值给基类类型的变量或参数,但反之不行。
  • 多重继承:Delphi 不支持多重继承。可以使用接口(interface)作为替代方案。

多态(Polymorphism)

  • 多态是指允许不同类的对象以自己的方式响应相同的消息(或方法调用)。
  • 这通常通过方法重写(覆盖父类中的方法)和接口(定义一组方法规范)实现。
  • 在 Delphi 中,你可以通过重写方法(使用 override 关键字)来实现多态

使用方法

  1. 方法重写(Overriding)

    • 在基类中声明虚方法(使用 virtual 关键字)。
    • 在派生类中重写这些方法(使用 override 关键字)。
type
  TAnimal = class
  public
    procedure Speak; virtual;
  end;

  TDog = class(TAnimal)
  public
    procedure Speak; override;
  end;

接口(Interface)

  • 定义一个接口。
  • 创建实现该接口的类。
  • 使用接口类型的引用来调用实现了该接口的不同类的方法。
type
  ISpeak = interface
    procedure Speak;
  end;

  TDog = class(TInterfacedObject, ISpeak)
    procedure Speak;
  end;

注意事项

  1. 虚方法

    • 只有被声明为 virtualdynamicabstract 的方法才可以被重写。
  2. 调用 inherited

    • 在重写的方法中使用 inherited 来调用基类的实现,除非你有意改变整个行为。
  3. 接口引用计数

    • 当使用接口时,Delphi 自动处理对象的引用计数。确保你了解引用计数和接口的管理方式。
  4. 方法隐藏

    • 如果在子类中声明了与基类同名的方法而没有使用 override 关键字,这将导致方法隐藏而非重写。

使用技巧

  1. 代码重用和扩展性

    • 使用多态可以在不更改现有代码的情况下扩展功能,这对于维护大型应用程序非常有用。
  2. 解耦

    • 使用接口可以降低类之间的耦合度,使得代码更加模块化。
  3. 测试和模拟

    • 在单元测试中,你可以使用多态来创建模拟对象(Mock Objects),这对于测试特定功能而不依赖于其他部分非常有用。
  4. 设计模式应用

    • 多态是许多设计模式(如工厂模式、策略模式等)的基础。
type
  TAnimal = class
  public
    procedure Speak; virtual;
  end;

  TDog = class(TAnimal)
  public
    procedure Speak; override;
  end;

procedure TAnimal.Speak;
begin
  ShowMessage('An animal makes a sound');
end;

procedure TDog.Speak;
begin
  ShowMessage('A dog barks');
end;

var
  Pet: TAnimal;
begin
  Pet := TDog.Create;
  try
    Pet.Speak;  // 输出:A dog barks
  finally
    Pet.Free;
  end;
end;

工厂类代码示例

        要在 Delphi 中实现一个展示继承和多态特性的工厂类,我们可以创建一个基类和几个继承自该基类的子类。然后,使用一个工厂类来根据不同的条件创建和返回这些子类的实例。以下是一个简单的示例:

基类和子类

首先,定义一个基类 TAnimal 和两个继承自它的子类 TDogTCat

type
  // TAnimal 是一个抽象基类
  TAnimal = class
  public
    // 声明一个抽象的虚方法 Speak
    function Speak: string; virtual; abstract;
  end;

  // TDog 是 TAnimal 的子类
  TDog = class(TAnimal)
  public
    // 重写基类的 Speak 方法
    function Speak: string; override;
  end;

  // TCat 也是 TAnimal 的子类
  TCat = class(TAnimal)
  public
    // 同样重写基类的 Speak 方法
    function Speak: string; override;
  end;

// 实现 TDog 的 Speak 方法
function TDog.Speak: string;
begin
  Result := 'Dog says: Woof!';
end;

// 实现 TCat 的 Speak 方法
function TCat.Speak: string;
begin
  Result := 'Cat says: Meow!';
end;

实现工厂类

接下来,我们定义一个工厂类 TAnimalFactory,用于根据不同的条件创建 TAnimal 类的不同子类的实例。

type
  // 动物类型的枚举
  TAnimalType = (atDog, atCat);

  // TAnimalFactory 是用于创建 TAnimal 对象的工厂类
  TAnimalFactory = class
  public
    // 静态方法 CreateAnimal 用于根据动物类型创建相应的动物实例
    class function CreateAnimal(AnimalType: TAnimalType): TAnimal;
  end;

// 实现 TAnimalFactory 的 CreateAnimal 方法
class function TAnimalFactory.CreateAnimal(AnimalType: TAnimalType): TAnimal;
begin
  case AnimalType of
    atDog: Result := TDog.Create; // 创建 TDog 实例
    atCat: Result := TCat.Create; // 创建 TCat 实例
  else
    Result := nil; // 未知类型返回 nil
  end;
end;

 

使用工厂类

最后,展示如何使用 TAnimalFactory 来创建不同的动物实例并调用它们的 Speak 方法。

var
  Animal: TAnimal;
  AnimalType: TAnimalType;
begin
  // 选择创建一个狗的实例
  AnimalType := atDog;

  // 使用工厂类创建动物实例
  Animal := TAnimalFactory.CreateAnimal(AnimalType);
  try
    if Assigned(Animal) then
      ShowMessage(Animal.Speak); // 显示: Dog says: Woof!
  finally
    Animal.Free; // 释放动物实例
  end;

  // 这里可以重复上述过程来创建和使用不同类型的动物
end;

        在这个示例中,TAnimalFactory 根据传入的动物类型枚举值动态地创建 TAnimal 类的合适子类实例。这展示了多态的使用,因为 Speak 方法的具体行为取决于对象的实际类别,而这些对象都是从同一个基类 TAnimal 继承的。通过这种方式,我们可以在不修改现有代码的情况下轻松添加新的动物类型。

  • 22
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thomas_Lbw

欣赏我就赏赐给我吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值