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

How Do I cast between 2 types that implement the same interface

我有一个重叠的数据对象,需要将其提供给几种计算方法中的至少一种,可能更多,以生成一个通用数据对象。

我认为最好通过同时实现协变和逆变来解决这个问题,但我还不能完全理解它会是什么样子,所以我对其他建议持开放态度。实际上 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 是一个具有抽象函数的抽象基础 class,它也可以工作。如果我理解正确,这意味着实现了协变行为,因为这是您对继承的期望。

 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 猫狗

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 视为猫,然后是狗,否则我不是在复制如何在两个地方吠叫和喵喵叫吗?

协变和逆变是泛型类型的属性(例如 List(Of IAnimal)),这与您的问题无关。

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