如何在实现相同接口的两种类型之间进行转换

时间:2017-03-20 17:49:18

标签: vb.net design-patterns contravariance

我有一个重叠的数据对象需要至少一个,可能更多的计算方法,以产生一个公共数据对象。

我认为这最好通过同时实施两种协变来解决,但我还没有能够理解这种情况会是什么样的,所以我对其他建议持开放态度。实际上,Animal / IAnimal和Noise有很多数据属性,所以我希望尽可能避免在构造函数中映射它们。

Public Class Noise
    Public Property Sound() As String
    Public Sub Listen()
        Console.WriteLine(sound)
    End Sub 
End Class

Public Interface IAnimal
    Function Speak() As Noise()
    Property Name() As String
End Interface

Public Class Dog
    Implements IAnimal
    Public Function Speak() As Noise() Implements IAnimal.Speak
        return { new Noise() with { .Sound = "Bark" } }
    End Function
    Public Property Name As String Implements IAnimal.Name
End Class

Public Class Cat
    Implements IAnimal
    Public Function Speak() As Noise() Implements IAnimal.Speak
        return { new Noise() with { .Sound = "Meow" } }
    End Function
    Public Property Name As String Implements IAnimal.Name
End Class

以下测试产生正确的输出,如果IAnimal是具有抽象函数说明的抽象基类,也可以工作。如果我理解正确,这意味着实现了协变行为,因为它是您对继承的期望。

 Public Sub ListenToAnimalsTest()
    dim spot = new Dog() With {.Name = "Spot" }
    dim kitty = new Cat() With {.Name = "Kitty" }

    Dim animalList As List(of IAnimal)
    animalList.Add(spot)
    animalList.Add(kitty)
    For Each animal in animalList 
        Console.WriteLine(animal.Name)
        animal.Speak().Listen()
    Next
End Sub

问题是我还需要一个是IAnimal的CatDog

Public Class CatDog
    Implements IAnimal

    Public Overrides Function Speak() As Noise() Implements IAnimal.Speak
        dim myself As Cat = me
        dim andI As Dog = me
        Return { myself.Speak(), andI.Speak()}
    End Function

   Public Property Name As String Implements IAnimal.Name
End Class

如果我可以使用逆变法允许将Animal或IAnimal投射到Cat或Dog,我试图解决这个问题,显然只会填充常见的属性。

有任何想法或建议吗?

关于装饰器/访客模式我希望能够继续通过进行父或接口的另一个实现来实现最终实现的任何模式,以便让动物说话不会改变。这意味着Decorator的catDog实现仍然需要将IAnimal视为猫,然后是狗或者我正在复制如何在两个地方吠叫和喵喵我不是吗?

1 个答案:

答案 0 :(得分:2)

协方差和逆变是泛型类型的属性(例如List(Of IAnimal)),它与您的问题并不相关。

VB.NET不允许真正的多重继承,但您可以创建每个实现ICat的接口IDogIAnimal。然后使用显式接口实现来使IAnimal树皮或喵喵声取决于您的对象被转换为哪个接口。