问题
I'm trying to wrap my head around inheritance/interfaces/implementation a bit better in .NET.
I have a class that's defined as follows (sort of):
Public Class Sheet
Property Name As String
Property Steps As List(Of [Step])
End Class
The thing is, [Step] is just a virtual, base class. There are 5 different concrete implementations of [Step]. To make matters a bit more complex, there are 3 DIRECT implementations of [Step], 2 of which are virtual. Each of those 2 has 2 subclasses that would concretely implement [Step].
So, here's how it looks:
Step
|-----------------|-----------------|
| | |
SubStepA SubStepB SubStepC
|----|----| |----|----|
| | | |
SubStepAA SubStepAB SubStepCA SubStepCB
So, SubStepB, SubStepAA, SubStepAB, SubStepCA and SubStepCB are the concrete implementations.
There are a couple of things that I'd like ANY Step to do, such as Clone().
So, I tried declaring the following in Step:
Public MustOverride Function Clone() As Step
The problem is that, when I attempt to implement that in SubStepAA, I can't declare the following:
Public Overrides Function Clone() As SubStepAA
If I do that, I get an error that the return types aren't the same.
Is the solution to this to just use a DirectCast call anytime I clone a concrete subclass? That seems odd and unsatisfying. It also just seems wrong. I mean, if I clone a SubStepAA object, I want to get back an object of type SubStepAA.
There's got to be a way to do this, right? I mean, I guess I could just declare each class the way it needs to be, but it also seems wrong to have to write 5 DIFFERENT Clone() methods that just HAPPEN to work in (essentially) the same way (creating a deep copy of the referenced object).
I've looked into using Interface declarations, but that seems to suffer from the same type mismatch error.
Please tell me that I'm just missing something basic!
Thanks!
As an aside, I have been doing some reading and I realize that there may be more optimized ways to do deep copies of object (e.g., through serialization/deserialization), but I'm still interested in this question, even if I choose to clone objects using a different approach.
回答1:
This may not be exactly what you are hoping for, but you can meet all your requirements by using a generic base type, like this:
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
However, then, there would be no common Step
base class that would be usable for all the derived types. For instance, there would be no way to do something like this:
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()
However, if you need to have a common base type like that, you could still do something like that, albeit with some additional complication:
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
If you did it that way, you would have that additional layer of abstraction where you could cast each concrete object as either a Step(T)
or as a Step
. For instance, you could then do this:
Dim s As [Step] = New StepA()
Dim c As [Step] = s.CloneBase()
But of course, this all begs the question, is it worth all this complication? The two simpler solutions would be to implement the interface independently on each derived class (and thereby forgo the ability to call clone from the base class), or else go with your first idea and just have the Clone
method always return the base type.
来源:https://stackoverflow.com/questions/14072206/vb-net-forced-inheritance-through-multiple-generations