我想编写一个包含方法的接口,该方法具有与实现类相同类型的参数。
目前我正在使用此:
Public Interface IContent(Of T)
Function ContentEquals(content As IContent(Of T)) As Boolean
End Interface
Public Class SpecificContent
Implements IContent(Of Specific)
Private m_Member As String
Public Function ContentEquals(content As IContent(Of Specific)) As Boolean Implements IContent(Of Specific).ContentEquals
' Actually I need to access content.m_Member here
' Of course this doesn't work
' since not every IContent(Of Specific) has m_Member
' just because SpecificContent does.
Return True
End Function
End Class
问题是,这个接口定义需要ContentEquals
的实现来接受实现IContent(Of Specific)
的任何类型的任何对象,而不仅仅是SpecificContent
实际上想要定义。
有没有办法在界面I
中定义一个方法,该方法强制使用A
的参数A Implements I
和B
B Impements I
的参数}, 一世。即类似于content As MyClass
?
答案 0 :(得分:2)
不,没有。坦率地说,这是一件好事。
想一想 - 你怎么能使用这样的界面?接口的要点是,无论实际实现接口的对象的类型如何,都可以调用某个方法。如果接口包含绑定到其实现者类型的方法,那么您将在哪个类型的变量中存储该接口?如果你可以将它存储在变量中,你会如何将它传递给一个不了解impelementor的方法,只知道接口?该方法如何能够调用接口,它将作为参数传递什么?
对于这种等式测试,您应该覆盖Object.Equals
方法,或引入明确接受您自己类型的Object.Equals
的另一个重载。您仍然可以使用界面,但参数必须是Object
类型,就像使用Object.Equals
一样。
答案 1 :(得分:0)
我找到了实现我想要的正确方法。解决方案是接口继承,并且是您希望作为参数类型的类型的第二个通用。我知道我以前做过类似的事情,但它是用Java编写的,我不记得了。
这些是我的界面:
Public Interface IContentFactory(Of T, S As IContent(Of T))
Function CreateFrom(obj As T) As IComparableContent(Of T, S)
End Interface
Public Interface IContent(Of T)
Sub ApplyTo(obj As T)
End Interface
Public Interface IComparableContent(Of T, S As IContent(Of T))
Inherits IContent(Of T)
Function ContentEquals(content As S) As Boolean
End Interface
在我的代码中,我可以将这些接口用于通用内容处理类:
Public Class ContentHistory(Of T, S As IContent(Of T))
Private m_Obj As T
Private m_Factory As IContentFactory(Of T, S)
Private m_History As Stack(Of IComparableContent(Of T, S))
Public Sub New(obj As T, factory As IContentFactory(Of T, S))
If obj Is Nothing Then Throw New ArgumentNullException("obj")
If factory Is Nothing Then Throw New ArgumentNullException("factory")
m_Obj = obj
m_Factory = factory
m_History = New Stack(Of IComparableContent(Of T, S))
End Sub
Public Sub Backup()
Dim currentContent = m_Factory.CreateFrom(m_Obj)
If m_History.Count = 0 OrElse Not m_History.Peek().ContentEquals(currentContent) Then
m_History.Push(currentContent)
End If
End Function
Private Sub Restore()
If m_History.Count > 0 Then
m_History.Pop().ApplyTo(m_Obj)
End If
End Function
End Class
现在我可以为内容对象及其工厂实现特定的类,如下所示:
Public Class SpecificContentFactory
Implements IContentFactory(Of Specific, SpecificContent)
Public Function CreateFrom(obj As Specific) As IComparableContent(Of Specific, SpecificContent) Implements IContentFactory(Of Specific, SpecificContent).CreateFrom
Return New SpecificContent(obj)
End Function
End Class
Public Class SpecificContent
Implements IComparableContent(Of Specific, SpecificContent)
Private ReadOnly m_Value As String
Friend Sub New(obj As Specific)
m_Value = obj.Value
End Sub
Public Sub ApplyTo(obj As Specific) Implements IContent(Of Specific).ApplyTo
obj.Value = m_Value
End Sub
Public Function ContentEquals(content As SpecificContent) As Boolean Implements IComparableContent(Of Specific, SpecificContent).ContentEquals
Return (content.m_Value = m_Value)
End Function
End Class
要设置此内容处理程序,我所要做的就是
Dim obj = New Specific()
Dim history = New ContentHistory(Of Specific, SpecificContent)(obj, New SpecificContentFactory())
我可以像
一样使用它obj.Value = "OldValue"
history.Backup
obj.Value = "OldValue"
history.Backup ' Nothing happens
obj.Value = "NewValue"
history.Backup
obj.Value = "EvenNewerValue"
Dim value = obj.Value ' "EvenNewerValue"
history.Restore
value = obj.Value ' "NewValue"
history.Restore
value = obj.Value ' "OldValue"
history.Restore ' Nothing happens
value = obj.Value ' "OldValue"
只要我提供SpecificContent
和SpecificContentFactory
实施,我就可以将ContentHistory(Of Specific, SpecificContent)
用于我喜欢的任何类型Specific
。