ZetCode

FreeBasic Extends 关键字

最后修改日期:2025 年 6 月 16 日

FreeBasic 的 Extends 关键字在面向对象编程中实现了继承。它允许派生类型继承基类型的成员。继承促进了代码的重用和类型之间的层次关系。

基本定义

在 FreeBasic 中,Extends 在类型之间创建了继承关系。派生类型继承基类型的所有字段和方法。派生类型可以添加新成员或覆盖继承的成员。

继承遵循“is-a”关系。例如,狗继承了动物,因为狗是一种动物。基类型更通用,而派生类型更具体。

简单继承

本示例使用 Extends 关键字演示了基本继承。

extends_simple.bas
Type Animal
    Public:
        name As String
        Declare Constructor(name As String)
        Declare Sub MakeSound()
End Type

Constructor Animal(name As String)
    This.name = name
End Constructor

Sub Animal.MakeSound()
    Print "Some generic animal sound"
End Sub

Type Dog Extends Animal
    Public:
        Declare Constructor(name As String)
        Declare Sub MakeSound()
End Type

Constructor Dog(name As String)
    Base(name)
End Constructor

Sub Dog.MakeSound()
    Print name; " says: Woof!"
End Sub

Dim d As Dog = Dog("Rex")
d.MakeSound()

在这里,Dog 继承了 Animal,继承了它的 name 字段。Dog 构造函数使用 Base() 调用基构造函数。Dog 通过自己的实现覆盖了 MakeSound()。这展示了多态性的应用。

访问基类成员

派生类型可以使用 Base 关键字访问基类成员。

extends_base.bas
Type Vehicle
    Public:
        speed As Integer
        Declare Constructor(speed As Integer)
        Declare Sub Display()
End Type

Constructor Vehicle(speed As Integer)
    This.speed = speed
End Constructor

Sub Vehicle.Display()
    Print "Speed: "; speed; " km/h"
End Sub

Type Car Extends Vehicle
    Public:
        model As String
        Declare Constructor(model As String, speed As Integer)
        Declare Sub Display()
End Type

Constructor Car(model As String, speed As Integer)
    Base(speed)
    This.model = model
End Constructor

Sub Car.Display()
    Base.Display()
    Print "Model: "; model
End Sub

Dim c As Car = Car("Toyota", 120)
c.Display()

Car 类型继承了 Vehicle 并添加了 model 字段。它的 Display() 方法在添加自己的输出之前调用基类的 Display()。Base 允许访问直接父类的成员。

多层继承

FreeBasic 支持多层继承链。

extends_multilevel.bas
Type Person
    Public:
        name As String
        Declare Constructor(name As String)
End Type

Constructor Person(name As String)
    This.name = name
End Constructor

Type Employee Extends Person
    Public:
        id As Integer
        Declare Constructor(name As String, id As Integer)
End Type

Constructor Employee(name As String, id As Integer)
    Base(name)
    This.id = id
End Constructor

Type Manager Extends Employee
    Public:
        department As String
        Declare Constructor(name As String, id As Integer, department As String)
        Declare Sub Display()
End Type

Constructor Manager(name As String, id As Integer, department As String)
    Base(name, id)
    This.department = department
End Constructor

Sub Manager.Display()
    Print "Name: "; name
    Print "ID: "; id
    Print "Department: "; department
End Sub

Dim m As Manager = Manager("Alice", 1001, "Engineering")
m.Display()

这展示了一个三层继承层次结构:Manager 继承了 Employee,而 Employee 继承了 Person。每个派生类型都添加了新字段,同时继承了所有先前的字段。Manager 构造函数通过两个父构造函数进行链接。

重写方法

派生类型可以覆盖基类型方法以提供专门的行为。

extends_override.bas
Type Shape
    Public:
        Declare Function Area() As Double
End Type

Function Shape.Area() As Double
    Return 0
End Function

Type Circle Extends Shape
    Public:
        radius As Double
        Declare Constructor(radius As Double)
        Declare Function Area() As Double
End Type

Constructor Circle(radius As Double)
    This.radius = radius
End Constructor

Function Circle.Area() As Double
    Return 3.14159 * radius * radius
End Function

Type Square Extends Shape
    Public:
        side As Double
        Declare Constructor(side As Double)
        Declare Function Area() As Double
End Type

Constructor Square(side As Double)
    This.side = side
End Constructor

Function Square.Area() As Double
    Return side * side
End Function

Dim shapes(1 To 2) As Shape Ptr
shapes(1) = New Circle(5.0)
shapes(2) = New Square(4.0)

For i As Integer = 1 To 2
    Print "Area: "; shapes(i)->Area()
    Delete shapes(i)
Next

Shape 定义了一个通用的 Area() 方法。Circle 和 Square 用它们各自的实现覆盖了它。Shape 指针数组展示了多态性——调用 Area() 会调用相应的派生类实现。

抽象基类

FreeBasic 可以使用纯虚方法来模拟抽象基类。

extends_abstract.bas
Type Animal Abstract
    Public:
        Declare Abstract Sub Speak()
End Type

Type Cat Extends Animal
    Public:
        Declare Sub Speak()
End Type

Sub Cat.Speak()
    Print "Meow"
End Sub

Type Dog Extends Animal
    Public:
        Declare Sub Speak()
End Type

Sub Dog.Speak()
    Print "Woof"
End Sub

Dim animals(1 To 2) As Animal Ptr
animals(1) = New Cat()
animals(2) = New Dog()

For i As Integer = 1 To 2
    animals(i)->Speak()
    Delete animals(i)
Next

Animal 类型被标记为 Abstract,并有一个 Abstract Speak() 方法。派生类型必须实现 Speak()。这强制执行了所有动物都必须遵循的接口。Abstract 关键字阻止了基类的实例化。

接口的多重继承

FreeBasic 通过抽象接口支持多重继承。

extends_interface.bas
Type IPrintable Abstract
    Public:
        Declare Abstract Sub Print()
End Type

Type IScannable Abstract
    Public:
        Declare Abstract Sub Scan()
End Type

Type Printer
    Public:
        Declare Sub Print()
End Type

Sub Printer.Print()
    Print "Printing document..."
End Sub

Type Scanner
    Public:
        Declare Sub Scan()
End Type

Sub Scanner.Scan()
    Print "Scanning document..."
End Sub

Type MultiFunctionDevice Extends Printer, Scanner
    Public:
        Declare Sub Fax()
End Type

Sub MultiFunctionDevice.Fax()
    Print "Sending fax..."
End Sub

Dim mfd As MultiFunctionDevice
mfd.Print()
mfd.Scan()
mfd.Fax()

这展示了多重继承。MultiFunctionDevice 同时继承了 Printer 和 Scanner。每个父类型都实现了不同的接口。派生类型结合了所有功能并添加了新功能。

构造函数链

继承层次结构中的构造函数必须正确地链接到基构造函数。

extends_constructors.bas
Type BaseType
    Public:
        value As Integer
        Declare Constructor(v As Integer)
End Type

Constructor BaseType(v As Integer)
    value = v
    Print "BaseType constructor: "; value
End Constructor

Type DerivedType Extends BaseType
    Public:
        text As String
        Declare Constructor(v As Integer, t As String)
End Type

Constructor DerivedType(v As Integer, t As String)
    Base(v)
    text = t
    Print "DerivedType constructor: "; text
End Constructor

Dim d As DerivedType = DerivedType(42, "Hello")
Print "Final object: "; d.value; ", "; d.text

DerivedType 构造函数必须使用 Base() 调用 BaseType 构造函数。构造函数从基类开始,一直调用到最派生的类型。字段的初始化顺序相同。正确的构造函数链可确保对象的完整初始化。

最佳实践

本教程涵盖了 FreeBasic 的 Extends 关键字,并通过各种场景下的实际示例展示了继承。正确使用继承可以带来更清晰、更易于维护的代码。

作者

我的名字是 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直在撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在教授编程方面拥有十多年的经验。

列出所有 FreeBasic 教程