将一个派生类转换为另一个?

时间:2014-10-14 17:40:10

标签: vb.net class oop inheritance

我有一个班级'timerecord'和两个班级'秒表'和'历史',它继承自这个类,但没有用任何其他属性或方法扩展它。他们的构造函数只是将继承的属性设置为不同的东西。

我希望能够做的是将一种类型的继承类转换为另一种类型(无需手动将所有属性从一种类型复制到另一种类型中)

我已经尝试了所有类型的ctype和directcast语句,但它们不起作用,我只能转换回继承的类,这不是我想要的。

除了他们的名字之外,所有类都是相同的。 我希望秒表对象变成一个历史对象..

有没有办法可以做到这一点?

如果我实现'timerecord'类以及继承?或者将'timerecord'传递给'秒表'和'历史'类构造函数并将其作为属性或其他东西?

一整天都在摸不着头脑,决定开个账户,问我似乎找不到答案。

Tldr;我想知道如何将一个派生类转换为另一个相同的(在所有名称中)派生类,如果它甚至可能?

谢谢

4 个答案:

答案 0 :(得分:0)

如果属性相同,您可以将stopwatch的实例序列化为字符串,然后将其反序列化为historic实例。

但是,我认为最好的解决方案是只有一个带有枚举类型属性的timerecord类,用于区分stopwatchhistoric实例。这样,您可以将timerecord类型枚举传递给构造函数,并根据枚举值以您需要的方式设置属性。

答案 1 :(得分:0)

最好使用枚举并基于它进行初始化。如果唯一的构造函数需要它,则总是必须创建一个或另一个。

Friend Enum TimeRecordTypes
    Undefined
    StopWatch
    Historic
End Enum

Public Class TimeRecord
    Public Property Name As String
    Public Property Foo As Integer 
    Public Property Bar As DateTime

    Public ReadOnly Property TimeRecordType As TimeRecordTypes = Undefined
    ...

    Public Sub New(e As TimeRecordTypes)
        Select Case e
            Case TimeRecordTypes.StopWatch
               do stopwatch stuff
            Case TimeRecordTypes.Historic
               do Historic stuff

         End Select 
    End Sub

    Public Sub ConvertTo(maybe an arg for the type)
       ' convert A to B
    End Sub

答案 2 :(得分:0)

(无需手动将所有属性复制到另一个属性中)

真的吗? 我认为,在某种程度上,你必须编写更复杂的代码来做这件事......

序列化/反序列化...大部分时间都是方便的。我用过这个..直到我在一个类中添加了一个Property而没有在同类中添加它们的对应物。像Point2D这样的类,其中X和Y为double,Vector2D,X和Y为double或Displacement2D,X和Y为double ...直到我添加了属性Length在Vector2D ......以及后来的Displacement2D中的Distance:/

定义对象类型的属性(枚举)。同上:在某个方面,为了便于使用,您可以将成员添加到其他类中无关的类中。 :/这会使你的对象无法成长/进化,对于非使用/假成员都是奇怪的......

所以最后,我认为你必须在当前状态(成员)“冻结”你的课程或编写处理转换所需的每个代码之间做出选择,并在需要时更新这些代码(添加/编辑成员) )


使用CType扩展怎么样?

Public Class StopWatch
    Inherits TimeRecord

    ' ...

    Public Shared Widening Operator CType(ByVal HistoricInstance As Historic) As StopWatch
        Dim NewStopWatch As StopWatch
        If HistoricInstance IsNot Nothing Then
            NewStopWatch = New StopWatch(...)
            ' Set NewStopWatch Properties here...
            ' ...
            Return NewStopWatch
        Else
            Return Nothing
        End If
    End Operator
End Class

并且:

Public Class Historic
    Inherits TimeRecord

    ' ...

    Public Shared Widening Operator CType(ByVal StopWatchInstance As StopWatch) As Historic
        Dim NewHistoric As Historic
        If StopWatchInstance IsNot Nothing Then
            NewHistoric = New Historic(...)
            ' Set NewHistoric Properties here...
            ' ...
            Return NewHistoric
        Else
            Return Nothing
        End If
    End Operator
End Class

注意:如果您将一个属性添加到StopWatch,但不添加到Historic,则StopWatch CType运算符将变为Narrowing而不是Widening。

当然,每次将一个类转换为另一个类时,这将创建该类的新实例。有时,当您希望两个类使用相同的包含对象(不是新实例)并且几个月后,这不会很方便,你忘了你已经用一种方法编写了扩展运算符来创建所有成员的新实例......

假设您有一个类型为StopWatch的MyStopWatch类,以及一个在构造函数中设置为Date.Now的属性InitializationDateTime。

MyStopWatch = New StopWatch() ' .InitializationDateTime = Date.Now
' do some stuff...
MyHistoric = CType(MyStopWatch, Historic) ' where MyHistoric.InitializationDateTime = Date.Now

使用上面的代码,你将拥有不同的属性InitializationDateTime值,即使你假设你已经正确地将MyTimeRecord转换为MyHistoric,这是因为CType后来在创建了一个Historic实例时间比MyTimeRecord初始化时。

那怎么样?序列化,TypeCode属性/枚举或CType扩展?

Plutonix有另一种方式:

Public Class StopWatch()
    Public Sub New(ByVal HistoricInstance As Historic)
        ' Copy Properties values here...
    End Sub
End Class
' Do the same for Historic Class.

或者您也可以制作函数(VB.net含义)

Public Class StopWatch()
    Public Function ToHistoric() As Historic
        Dim NewHistoric As New Historic()
        ' .. set NewHistoric Properties values here
        Return NewHistoric
    End Function
End Class

但结果是一样的:你必须编写代码来逐个设置属性值。好处是:你编写一次代码,最终更新它,但你只需一行代码就可以随时使用它......

DirectCast很方便,但容易发生运行时崩溃 TryCast很有趣,但无论如何你都要检查是否失败。 :/

还有其他方法可以做到,但是从现在开始,提议的方法之一是否足够有用,或者您有一些特定的要求,例如上面的问题?

答案 3 :(得分:0)

我尝试过所提供的解决方案,并且这样做后才意识到解决方案不是使用继承,而是使用接口,因为它们完全相同但名称不同。 我创建了一个接口,还有另一个类' basetimerecord',这三个类都实现了这个接口。 basetimerecord的属性指向变量。

其他类属性指向basetimerecord类型的私有变量的属性。 basetimerecord通过public read only属性公开。 这些类中的每个类的构造函数都可以将基准时间记录作为参数。当他们这样做时,他们用它覆盖他们自己的私有变量,因此我可以通过每次只更改一个私有变量来复制所有属性。

我现在可以做历史性的=新历史性的(stopwatch.basetimerecord)

相关问题