成员过程
- 来源: https://www.freebasic.net/wiki/wikka.php?wakka=ProPgMemberProcedures
- 最后更新: 2021-09-28
可完整访问 Type 或 Class 成员的过程
声明和定义 声明和定义成员过程。
使用 调用成员过程。
隐藏参数 This 对调用非静态成员过程的实例的隐式访问。
访问权限 在成员过程中引用其他成员。
重载 声明两个或多个同名成员过程。
静态成员过程 与非静态成员过程的区别。
- 术语"成员过程"指静态和非静态成员过程,除非另有说明。
声明和定义
成员过程的声明方式与普通模块级过程非常相似,区别在于它们在 Type 或 Class 定义内声明,而在其外定义[1]。
在定义成员过程时,过程名称以 Type 或 Class 的名称以及成员访问运算符(Operator . (Member access))为前缀。在 Type 或 Class 定义中没有匹配声明的情况下定义成员过程会导致错误。
以下示例声明并定义了 Sub 和 Function 成员过程:
start GeSHi
'' foo1.bi
Type foo
Declare Sub f (As Integer)
Declare Function g As Integer
i As Integer
End Type
Sub foo.f (n As Integer)
Print n
End Sub
Function foo.g As Integer
Return 420
End Functionend GeSHi
使用
成员过程的引用方式与成员数据相同,即其名称以对象实例的名称和成员访问运算符(Operator . (Member access))为前缀[2]。
以下示例使用上一个示例的代码,调用 Sub 和 Function 成员过程:
start GeSHi
'' ... foo with non-static members as before ...
#include once "foo1.bi"
Dim bar As foo
bar.f(bar.g())end GeSHi
隐藏参数 This
成员过程实际上比声明时多一个参数[3]。当使用实例名称和 Operator . (Member access) 调用成员过程时,对该实例的引用会与调用中的其他参数一起传递,从而允许成员过程直接访问该实例。
编译器添加的额外参数称为 This,由于它是一个引用,对 This 的任何修改实际上都是对调用成员过程时传递的实例的修改。你可以像使用任何其他变量一样使用 This,例如,将其传递给接受相同类型对象的过程,使用 Operator . (Member access) 调用其他成员过程和访问成员数据,等等。
然而,大多数情况下,显式使用 This 是不必要的;成员过程可以通过名称直接引用传递给它们的实例的其他成员,而不必使用 This 和 Operator . (Member access) 进行限定。只有在成员名称被隐藏时(例如被参数或局部变量隐藏),才需要用 This 限定成员名称。在这些情况下,限定成员名称是引用这些隐藏成员名称的唯一方式。
Note:
To access duplicated symbols defined as global outside the Type, add one or preferably two dot(s) as prefix:.SomeSymbolor preferably..SomeSymbol(or only..SomeSymbol if inside a With..End With block).
以下示例使用 This 关键字引用被参数和局部变量隐藏的成员数据:
start GeSHi
Type foo
Declare Sub f (i As Integer)
Declare Sub g ()
i As Integer = 420
End Type
Sub foo.f (i As Integer)
'' A parameter hides T.i, so it needs to be qualified to be used:
Print This.i
End Sub
Sub foo.g ()
'' A local variable hides T.i, so it needs to be qualified to be used:
Dim i As Integer
Print This.i
End Subend GeSHi
访问权限
与普通模块级过程不同,成员过程对其声明所在的 Type 或 Class 的成员具有完整访问权限;它们可以引用 Type 或 Class 的公共、受保护和私有成员。
重载
一个成员过程可以被声明与另一个成员过程同名,只要参数不同(参数数量或类型不同)。这称为重载。
只有参数用于确定过程声明是否为有效重载。例如,Type 或 Class 可以具有同名的静态和非静态成员过程,或同名的 Sub 和 Function 成员过程。
与模块级过程不同(需要在声明中指定 Overload 子句才能允许重载),成员过程默认是可重载的,不需要 Overload 子句。
start GeSHi
Type T
Declare Sub f
'' Different number of parameters:
Declare Sub f (As Integer)
'' Different type of parameters:
Declare Sub f (ByRef As String)
'' Again, parameters are different:
Declare Function f (As UByte) As Integer
'' following three members would cause an error,
'' number of parameters and/or types do not differ:
'' Declare Function f As Integer
'' Declare Function f (As UByte) As String
'' Declare Static Function f (As UByte) As Integer
'' ...
somedata As Any Ptr
End Typeend GeSHi
静态成员过程
静态成员过程的声明和定义方式与非静态成员过程基本相同,但在声明和定义之前有 Static 关键字。
使用 Static 关键字定义的成员过程必须在 Type 或 Class 定义中用 Static 关键字声明,否则会出现编译器错误。与非静态成员过程一样,在 Type 或 Class 定义中没有匹配声明的情况下定义静态成员过程也是错误的。
不要将其与通过在过程头附加 Static 关键字来为其变量和对象指定静态存储的过程定义混淆。然而,Static 关键字可以在两种上下文中使用;静态成员过程可以定义为具有静态变量和对象存储。
以下示例声明了两个静态成员过程,第一个也具有静态变量和对象存储。注意,Static 关键字在成员过程定义中是可选的:
start GeSHi
'' foo2.bi
Type foo
Declare Static Sub f (As Integer)
Declare Static Function g As Integer
i As Integer
End Type
Static Sub foo.f (n As Integer) Static
Print n
End Sub
Function foo.g As Integer
Return 420
End Functionend GeSHi
静态成员过程可以像非静态成员过程一样调用,用实例名称和成员访问运算符(Operator . (Member access))限定过程名称。
也可以通过用声明它们的 Type 或 Class 的名称和成员访问运算符(Operator . (Member access))限定过程名称来调用它们。换句话说,调用静态成员过程不需要实例。
以下示例使用上一个示例的代码,演示了两种调用静态成员过程的方式:
start GeSHi
'' ... foo with static members as before ...
#include once "foo2.bi"
Dim bar As foo
bar.f(foo.g())end GeSHi
与非静态成员过程(声明时带有额外的 This 参数)不同,静态成员过程在调用时不会传递实例。因此,静态成员过程只能不加限定地引用常量、枚举、其他静态成员(数据或过程)等。静态成员过程仍然可以在用实例限定时引用非静态成员,例如:参数或局部变量。
以下示例从静态过程中引用非静态成员:
start GeSHi
Type foo
Declare Static Sub f (ByRef As foo)
i As Integer
End Type
Sub foo.f (ByRef self As foo)
'' Ok, self is an instance of foo:
Print self.i
'' would cause error
'' cannot access non-static members, no foo instance:
'' Print i
End Subend GeSHi
[1] 将来,成员过程可能可以在 Type 或 Class 定义内部定义。
[2] 静态成员过程不需要对象实例即可调用。
[3] 静态成员过程没有编译器添加的这个额外参数,因此无法访问调用它的对象实例。
返回 目录