2013-03-07 62 views
2

採取這樣的場景:約束的VB泛型 - 類型轉換和繼承?

Public Interface IMyClass 
End Interface 

Public mustinherit class MyBaseClass : implements IMyClass 
End Class 

public class MyClass : inherits MyBaseClass 
End Class 

public class MyModel(of t as IMyClass) 

    private Dim _parameter as t 

    Public Sub New(byval parameter As t) 
     _parameter As t 
    End Sub 
End class 

在我的控制,我可以沒有問題做到這一點:

Dim _myclass as IMyClass = new MyClass() 

我可以做這個類似的東西:

Dim _myModel as MyModel(of IMyClass) = new MyModel(of MyClass) 

? ?

我最初的想法是錯誤的,因爲我認爲轉換可以自動完成,但似乎沒有完成。任何方式在.NET中實現相同的東西?

編輯 我更新了爲MyModel類表現出更多的我在做什麼。我想限制我創建的實例,但接下來要做的是對傳統非泛型代碼進行縮小轉換。基本上,我的部分Razor視圖需要顯式模型,這些視圖最終呈現另一個視圖,將採用該模型並顯示它。因爲模型都實現或繼承了一個實現IMyClass的類,所有的方法都應該存在於所有的實例上,並且應該是可調用的,但是這些類型是不可互換的。

+0

適用於C#,但是這將適用於你的情況。 http://stackoverflow.com/questions/1078423/c-sharp-is-variance-covariance-contravariance-another-word-for-polymorphis – 2013-03-08 02:46:05

+0

這是指一個列表,而不是一個單一的實例。 – ps2goat 2013-03-08 15:43:24

+0

編輯我想要做的。 @ DanielA.White,如果你能給我一個例子,說明在這種情況下這將如何適用,我會很感激。 List(T)的用例是有道理的,但我不能100%確定如何在這種情況下應用它。 – ps2goat 2013-03-08 15:53:00

回答

1

稍微修改MyModel吧?

Public Class MyModel(Of T As IMyClass) 
    Private _parameter As T 

    Public Sub Something(parameter As T) 
     _parameter = parameter 
    End Sub 
End class 

Public Class MyClassA : Inherits MyBaseClass 
End Class 

Public Class MyClassB : Inherits MyBaseClass 
End Class 

Dim _myModel As MyModel(Of IMyClass) = New MyModel(Of MyClassA)() 
_myModel.Something(New MyClassB()) ' Boom! 

如果分配被允許的最後一行將帶來一個問題:MyMode(Of MyClassA)._parameter的類型爲MyClassA但最後一行將分配的(無關)的對象類型MyClassB。這是非法的,因此VB禁止它。

0

您是否需要MyModel的多個變種,或者您只是試圖要求將存儲的對象限制爲IMyClass?

最簡單的方法(可能不是你所需要的一切):在複雜

Public Interface IMyClass 
    Sub DoIt() 
End Interface 

Public Class MyModel 
    Private ReadOnly _parameter As IMyClass 
    Public Sub New(parameter As IMyClass) 
     _parameter = parameter 
    End Sub 
    Public Sub DoItToIt() 
     _parameter.DoIt() 
    End Sub 
End Class 

Public Class MyClassA 
    Implements IMyClass 
    Public Sub DoIt() Implements IMyClass.DoIt 
    End Sub 
End Class 

Public Class Tests 
    Public Sub Main() 
     Dim model1 As MyModel = New MyModel(New MyClassA) 
     model1.DoItToIt() 
    End Sub 
End Class 

下一步,就是堅持以定義一個接口IHasMyClass爲包含IMyClass類。這支持基於允許的類型的操作,實際類型,所含對象:

Public Interface IMyClass 
    Sub DoIt() 
End Interface 

Public Interface IHasMyClass 
    Function GetIt() As IMyClass 
    Function GetItsType() As Type 
    Function GetAllowedType() As Type 
End Interface 

Public Class MyModel(Of T As IMyClass) 
    Implements IHasMyClass 

    Private ReadOnly _parameter As IMyClass 
    Public Sub New(parameter As IMyClass) 
     _parameter = parameter 
    End Sub 
    Public Sub DoItToIt() 
     _parameter.DoIt() 
    End Sub 

    Public Function GetItAsT() As T 
     Return _parameter 
    End Function 

    Public Function GetIt() As IMyClass Implements IHasMyClass.GetIt 
     Return _parameter 
    End Function 

    Public Function GetItsType() As Type Implements IHasMyClass.GetItsType 
     Return _parameter.GetType() 
    End Function 

    Public Function GetAllowedType() As Type Implements IHasMyClass.GetAllowedType 
     Return GetType(T) 
    End Function 
End Class 

Public Class MyClassA 
    Implements IMyClass 
    Public Sub DoIt() Implements IMyClass.DoIt 
    End Sub 
End Class 

Public Class Tests 
    Public Sub Main() 
     ' Allow any IMyClass 
     Dim model1 As MyModel(Of IMyClass) = New MyModel(Of IMyClass)(New MyClassA) 
     model1.DoItToIt() 
     Dim it As IMyClass = model1.GetIt() 
     Dim allowedT As Type = model1.GetAllowedType() 

     ' Restrict to MyClassA 
     Dim modelA As MyModel(Of MyClassA) = New MyModel(Of MyClassA)(New MyClassA) 
     modelA.DoItToIt() 
     Dim itA1 As IMyClass = modelA.GetIt() 
     Dim itA2 As MyClassA = modelA.GetItAsT() 
     Dim allowedTA As Type = modelA.GetAllowedType() 
    End Sub 
End Class 

在測試中(),請注意,我們現在需要聲明是否我們正在創建一個可以接受任何IMyClass MyModel(Of IMyClass)一個爲MyModel,或者需要特定子類MyModel(Of MyClassA)

如果我們想操縱MyModels,這可以是上述類型的,我們使用了常用的接口:

Dim model As IHasMyClass 
model = model1 
... 
model = modelA 

或者在你的情況下,支持爲MyModel的所有功能,重命名IHasMyClassIMyModel ,並添加各種功能爲MyModel,但不是T,使用IMyClass

Public Interface IMyModel 
    Function GetIt() As IMyClass 
    Function GetItsType() As Type 
    Function GetAllowedType() As Type 

    Sub DoItToIt() 
    Function CompareIt(other As IMyClass) As Integer 
End Interface 

並作出適當的修改/添加到IMyClass和爲MyModel。

然後就有可能做到:

Dim model As IMyModel = modelA 
If model.CompareIt(model1.GetIt()) > 0 ...