如何 MustOverride Shared/Constructor 函数 Visual Basic

How To MustOverride Shared/Constructor Function Visual Basic

我目前正在为一个大学项目使用 Visual Basic,该项目要求我们制作一个简单的数据库系统。对于我的系统,我有一个名为 Record 的基础(抽象)class,它由我的数据库中的不同类型的记录继承,例如Member, User, Role.

我正在将我的数据保存在 csv 文件中,并且已经写了一个 CSVHandler class。但是,我想要一种优雅的方法来构造一个从 Record 派生的 class 的实例,其中的字符串来自 CSVHandler.

这就是问题所在。我能想到的唯一方法是在从 Record 派生的每个 class 中创建一个 ConstrcutorShared Function。但是,Visual Basic 不允许您将 ConstructorsShared Functions 也设为 MustOverride.

这是我希望编写的代码:

' Base Class
Public MustInherit Class Record
    Public MustOverride Shared Function fromString(ByVal str as String) As Record
End Class

' Example Of Class Derived From Record
Public Class User
    Inherits Record 

    Private _id As String
    Private _name As String

    Public Sub New(ByVal id As String, ByVal name As String)
        _id = id
        _name = name
    End Sub

    Public Overrides Shared Function fromString(ByVal str as String) As Record
        Dim strs() As String = str.Split(",")
        Return New User(strs(0), strs(1))
    End Function
End Class

' Example Of Creating Instacnce Of User
Dim user1 = User.fromString("1671,Kappeh")

有没有办法实现这种效果?

让你的构造函数调用一个 Protected MustOverride 方法来进行初始化。

Public MustInherit Class Record

    'This is required because each derived constructor must be able to implicitly invoke a parameterless
    'base constructor if it doesn't explicitly invoke a base constructor with parameters.
    Protected Sub New()
    End Sub

    Public Sub New(csv As String)
        Init(csv)
    End Sub

    Protected MustOverride Sub Init(csv As String)

End Class

Public Class User
    Inherits Record

    Private Property Id As String
    Private Property Name As String

    'This is still required because you can use a base constructor directly to create a derived instance.
    Public Sub New(csv As String)
        MyBase.New(csv)
    End Sub

    Public Sub New(id As String, name As String)
        Id = id
        Name = name
    End Sub

    Protected Overrides Sub Init(csv As String)
        'Add your type-specific implementation here.
    End Sub

End Class

这个 "solution" 实际上并没有像我想的那样,因为虽然它强制您在派生 class 中覆盖 Init,但您仍然必须提供派生调用调用 Init 的基本构造函数的构造函数,您仍然无法强制执行它。我认为我会把它留作答案,因为虽然它实际上并没有为您的问题提供解决方案,但它进一步说明了为什么(据我所知)没有这样的解决方案。

以下与@jmcilhinney 的回答类似,它强制派生的 class 实现初始化方法。然而,它使用了一个通用的共享函数,并使用鲜为人知的 GetUninitializedObject method 来绕过使用通用的 New 约束,这是一个可访问的无参数构造函数的要求。

Public MustInherit Class Record
    Public Shared Function fromString(Of T As {Record})(ByVal str As String) As T
        ' create an unintialized instance of T 
        Dim ret As T = DirectCast(System.Runtime.Serialization.FormatterServices.GetUninitializedObject(GetType(T)), T)
        ret.Initialize(str)
        Return ret
    End Function

    Protected MustOverride Sub Initialize(source As String)
End Class

然后Userclass会是这样的:

Public Class User : Inherits Record
    Private _id As String
    Private _name As String

    Public Sub New(ByVal id As String, ByVal name As String)
        _id = id
        _name = name
    End Sub

    Protected Overrides Sub Initialize(source As String)
        Dim strs() As String = source.Split(","c)
        _id = strs(0)
        _name = strs(1)
    End Sub
End Class

用法示例:

Dim userRecord As User = Record.fromString(Of User)("1,2")