FreeBasic Extends 关键字
最后修改日期:2025 年 6 月 16 日
FreeBasic 的 Extends 关键字在面向对象编程中实现了继承。它允许派生类型继承基类型的成员。继承促进了代码的重用和类型之间的层次关系。
基本定义
在 FreeBasic 中,Extends 在类型之间创建了继承关系。派生类型继承基类型的所有字段和方法。派生类型可以添加新成员或覆盖继承的成员。
继承遵循“is-a”关系。例如,狗继承了动物,因为狗是一种动物。基类型更通用,而派生类型更具体。
简单继承
本示例使用 Extends 关键字演示了基本继承。
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 关键字访问基类成员。
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 支持多层继承链。
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 构造函数通过两个父构造函数进行链接。
重写方法
派生类型可以覆盖基类型方法以提供专门的行为。
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 可以使用纯虚方法来模拟抽象基类。
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 通过抽象接口支持多重继承。
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。每个父类型都实现了不同的接口。派生类型结合了所有功能并添加了新功能。
构造函数链
继承层次结构中的构造函数必须正确地链接到基构造函数。
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 构造函数。构造函数从基类开始,一直调用到最派生的类型。字段的初始化顺序相同。正确的构造函数链可确保对象的完整初始化。
最佳实践
- 设计:仅在真正的“is-a”关系中使用继承。
- 深度:为了清晰起见,将继承深度限制为 2-3 层。
- 组合:优先使用组合而不是深度继承。
- 抽象:使用抽象基类来定义接口。
- 虚:当方法应该可以被覆盖时,将其标记为虚。
本教程涵盖了 FreeBasic 的 Extends 关键字,并通过各种场景下的实际示例展示了继承。正确使用继承可以带来更清晰、更易于维护的代码。