首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用锅炉板加强型式

用锅炉板加强型式
EN

Code Review用户
提问于 2014-09-27 02:05:35
回答 2查看 150关注 0票数 3

这是通过伪继承我的列表来实现Mat的毕多尼表。继承不是构建在VBA中的,但是可以通过组合继承的类并模仿它的所有公共方法和成员来模拟它。因为基类的修改需要传播到所有子类,所以它是一个PITA。

实现很简单,只需添加一个私有字符串数据成员pTypedName,并且每当客户端代码试图添加TypeName(Element) <> pTypedName引发类型错误的元素时。

TypedList

私人会员

代码语言:javascript
复制
Private this As List
Private pTypedName As String

私有方法

键入要添加到列表中的元素。如果尚未设置类型,则让此元素设置类型名。否则,如果错误类型不正确,则引发错误。

代码语言:javascript
复制
Private Sub TypeCheck(ByVal element As Variant, ByVal source As String)

    If pTypedName = vbNullString Then pTypedName = TypeName(element)
    If (TypeName(element) <> pTypedName) Then RaiseTypeError element, source

End Sub

因此

代码语言:javascript
复制
Dim tList as New TypedList
tList.Append "A"

是有效的,现在tList是String类型。

在允许任何元素进入列表之前,我们还希望检查序列中的每个元素。如果我们的字符串列表是用Array("a", "b", "C", 2)扩展的,我们不希望任何元素进入这个列表。

代码语言:javascript
复制
Private Sub TypeCheckSequence(ByVal sequence As Variant, ByVal source As String)

    Dim element As Variant
    For Each element In sequence
        TypeCheck element, source
    Next element

End Sub

以上两种方法都是在我们的TypedList中设置数据的任何方法开始时的锅炉板代码。

这是在失败时引发的错误。

代码语言:javascript
复制
Private Sub RaiseTypeError(ByVal badItem As Variant, ByVal method As String)
    Err.Raise 13, method, "Element is of type " & TypeName(badItem) & _
                         ", not " & TypedName & "."
End Sub

枚举

注意,我们使用this.NewEnum而不是this.[_NewEnum],就像在List类中一样。

代码语言:javascript
复制
Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_UserMemId = -4

    Set NewEnum = this.NewEnum

End Property

公共方法

客户端代码可以问TypedList它的类型是什么,并且只有当列表为空时才设置类型。

代码语言:javascript
复制
Public Property Get TypedName() As String

    TypedName = pTypedName

End Property
Public Property Let TypedName(ByVal typeName_ As String)

    If this.Count > 0 Then
        Err.Raise 9, TypeName(Me) & ".TypedName", _
            "Can only set typename of an empty list."
    End If

    pTypedName = typeName_

End Property

在这之后,这是相当无聊和多余的。我希望我没必要把这些都写出来。

TypeCheck入口

使用类型检查BoilerPlate代码模拟所有入口点。

替换

代码语言:javascript
复制
Public Property Let Item(ByVal index As Long, ByVal element As Variant)
Attribute Item.VB_UserMemId = 0

    TypeCheck element, TypeName(Me) & ".Item"
    this.Item(index) = element

End Property

Public Property Set Item(ByVal index As Long, ByVal element As Variant)
Attribute Item.VB_UserMemId = 0

    TypeCheck element, TypeName(Me) & ".Item"
    Set this.Item(index) = element

End Property

Public Property Let Slice(ByVal a As Long, ByVal b As Long, ByVal s As Integer, ByVal sequence As Variant)

    TypeCheckSequence sequence, TypeName(Me) & ".Slice"
    this.Slice(a, b, s) = sequence

End Property

扩展

代码语言:javascript
复制
Public Sub Append(ByVal element As Variant)

    TypeCheck element, TypeName(Me) & ".Append"
    this.Append element

End Sub

Public Sub Extend(ByVal sequence As Variant)

    TypeCheckSequence sequence, TypeName(Me) & ".Extend"
    this.Extend sequence

End Sub

插入

代码语言:javascript
复制
Public Sub Emplace(ByVal index As Long, ByVal element As Variant)

    TypeCheck element, TypeName(Me) & ".Emplace"
    this.Emplace index, element

End Sub

Public Sub Insert(ByVal index As Long, ByVal sequence As Variant)

    TypeCheckSequence sequence, TypeName(Me) & ".Insert"
    collec.Insert sequence, index

End Sub

默认接口

现在它只是模仿所有其他的方法。甚至更无聊..。

访问

代码语言:javascript
复制
Public Property Get Item(ByVal index As Long) As Variant
Attribute Item.VB_UserMemId = 0
    seq.Assign Item, this.Item(index)
End Property

Public Property Get Slice(ByVal a As Long, ByVal b As Long, ByVal s As Integer) As List
    Set Slice = this.Slice(a, b, s)
End Property

去除

代码语言:javascript
复制
Public Sub Remove(ByVal index As Long)
    this.Remove index
End Sub

Public Sub Clear(ByVal start As Long, ByVal size As Long)
    this.Clear start, size
End Sub

Aux

代码语言:javascript
复制
Public Function Count() As Long
    Count = this.Count
End Function

Public Function Exists(ByVal sought As Variant) As Boolean
    Exists = this.Exists(sought)
End Function

Public Function ToString() As String
    ToString = this.ToString
End Function
EN

回答 2

Code Review用户

回答已采纳

发布于 2014-09-27 14:50:59

总之,我觉得这个看起来不错。如果没有适当的继承,你就会被那些只需调用私人的List's属性的锅炉板属性所困扰。关于这一点,一切都做对了,vba就是那样糟糕。

我唯一真正注意到的是,我不喜欢你用神奇的数字来增加错误的方式。

Err.Raise 9, TypeName(Me) & ".TypedName", \_ "Can only set typename of an empty list."

私有子RaiseTypeError(ByVal badItem作为变体,ByVal方法作为字符串) Err.Raise 13,方法,元素类型为“& TypeName(badItem) & ",而不是”& TypedName &“。结束子对象

首先,我发现在一个地方使用潜艇是一致的,而在另一个地方则是直接提升。我知道您现在只在一个地方使用错误#9,但是将其删除肯定会使将来在其他地方使用它更容易。

但我提到了神奇的数字不是吗?通常,我建议定义一些模块作用域常量,以明确代码正在引发下标超出范围类型失配错误(分别),但这些都是在我们正在引发的VB错误中生成的。我们可能会在许多地方使用这些模块。有鉴于此,我认为创建一个带有公共VbErrorNumbers Enum的模块是绝对值得的。这是一项工作,但你只需要做一次。事实上,我相信今天晚些时候我会亲自动手。在这里可以找到内置的VBA错误的完整列表.在这里可以找到内置的VBA错误的完整列表..

票数 3
EN

Code Review用户

发布于 2014-09-27 15:17:56

我能补充的一点是@RubberDuck没有提到的一点是,使用this标识符来引用封装的List可能会让人困惑.但是,可能只是因为我有一个使用this的约定来引用一种私有类型,该类型将实例的私有字段合并到单个实体下;我会将其称为类似于encapsulatedunderlying的类型。不过没什么大不了的。

我喜欢你拒绝一个数组/序列,其中一个元素不是“类型安全”,它非常整洁。

票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/64004

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档