我正试图在.NET中更好地处理继承/接口/实现。
我有一个类定义如下(排序):
Public Class Sheet
Property Name As String
Property Steps As List(Of [Step])
End Class
问题是,[Step]只是一个虚拟的基类。 [Step]有5种不同的具体实现。为了使事情变得更复杂,[步骤]有3个DIRECT实现,其中2个是虚拟的。这两个中的每一个都有2个子类,具体实现[Step]。
所以,这是它的外观:
Step
|-----------------|-----------------|
| | |
SubStepA SubStepB SubStepC
|----|----| |----|----|
| | | |
SubStepAA SubStepAB SubStepCA SubStepCB
因此,SubStepB,SubStepAA,SubStepAB,SubStepCA和SubStepCB是具体实现。
我想要做任何事情,比如Clone()。
所以,我尝试在步骤中声明以下内容:
Public MustOverride Function Clone() As Step
问题在于,当我尝试在SubStepAA中实现它时,我无法声明以下内容:
Public Overrides Function Clone() As SubStepAA
如果我这样做,我会收到错误,返回类型不一样。
解决这个问题的方法是,只要我克隆一个具体的子类,就可以使用DirectCast调用吗?这看似奇怪而且不尽如人意。这也似乎是错的。我的意思是,如果我克隆一个SubStepAA对象,我想要找回一个SubStepAA类型的对象。
必须有办法做到这一点,对吧?我的意思是,我想我可以按照它需要的方式声明每个类,但是编写5个不同的Clone()方法似乎也是错误的,这些方法只是HAPPEN(基本上)以相同的方式工作(创建深层副本)被引用的对象)。
我已经研究过使用接口声明,但这似乎遇到了相同的类型不匹配错误。
请告诉我,我只是遗漏了一些基本的东西!
谢谢!
顺便说一下,我一直在做一些阅读,我意识到可能有更优化的方法来做对象的深层复制(例如,通过序列化/反序列化),但我仍然对这个问题感兴趣,即使我选择使用不同的方法克隆对象。
答案 0 :(得分:2)
这可能不是您所希望的,但您可以使用通用基本类型满足您的所有要求,如下所示:
Public MustInherit Class [Step](Of T)
Public MustOverride Function Clone() As T
End Class
Public Class StepA
Inherits [Step](Of StepA)
Public Overrides Function Clone() As StepA
' ...
End Function
End Class
然而,没有可用于所有派生类型的通用Step
基类。例如,没有办法做这样的事情:
Dim s As [Step] = New StepA() 'Won't work because there is no Step type, only a generic Step(T) type
Dim c As [Step] = s.Clone()
但是,如果你需要这样的共同基类型,你仍然可以做类似的事情,虽然有一些额外的复杂性:
Public Interface ICloneable(Of T)
Function Clone() As T
End Interface
Public MustInherit Class [Step]
Implements ICloneable(Of [Step])
Public MustOverride Function CloneBase() As [Step] Implements ICloneable(Of [Step]).Clone
End Class
Public MustInherit Class [Step](Of T As [Step])
Inherits [Step]
Implements ICloneable(Of T)
Public Overrides Function CloneBase() As [Step]
Return Clone()
End Function
Public MustOverride Function Clone() As T Implements ICloneable(Of T).Clone
End Class
Public Class StepA
Inherits [Step](Of StepA)
Public Overrides Function Clone() As StepA
' ...
End Function
End Class
如果你这样做,你就可以拥有额外的抽象层,你可以将每个具体对象转换为Step(T)
或Step
。例如,您可以这样做:
Dim s As [Step] = New StepA()
Dim c As [Step] = s.CloneBase()
但当然,这一切都引出了一个问题,是否值得所有这些并发症?两个更简单的解决方案是在每个派生类上独立实现接口(从而放弃从基类调用克隆的能力),或者继续你的第一个想法,只需让Clone
方法返回基础类型。