Vb.net 当';右';一个依赖于它的两个参数的动态类型

Vb.net 当';右';一个依赖于它的两个参数的动态类型,vb.net,overloading,dynamic-typing,Vb.net,Overloading,Dynamic Typing,我很难从一个重载多次的子程序中选择正确的子程序,每个子程序都有两个参数。也许某种形式的双重分派是合适的,但当有两个参数具有两种(可能)不同的类型需要检查时,我看不到任何整洁的方法 从本质上讲,我创建的示例代码按预期执行,但在我看来,这是一种非常糟糕的执行方式。由于类型是在编译时确定的,我不能简单地通过传入我试图测试的两个对象来调用我想要的子对象: test(store(0),store(1)) 将只调用带有签名的测试子例程 Sub test(cA As Class1, cB As Class

我很难从一个重载多次的子程序中选择正确的子程序,每个子程序都有两个参数。也许某种形式的双重分派是合适的,但当有两个参数具有两种(可能)不同的类型需要检查时,我看不到任何整洁的方法

从本质上讲,我创建的示例代码按预期执行,但在我看来,这是一种非常糟糕的执行方式。由于类型是在编译时确定的,我不能简单地通过传入我试图测试的两个对象来调用我想要的子对象:

test(store(0),store(1)) 
将只调用带有签名的测试子例程

Sub test(cA As Class1, cB As Class1)
因为存储的静态类型(x)将始终为Class1

某种复杂的双重分派形式是可行的还是有更好的解决方案

Option Strict On
Module Module1

    Sub Main()
        Dim store As List(Of Class1) = New List(Of Class1)
        store.Add(New Class2)
        store.Add(New Class3)
        If TypeOf (store(0)) Is Class2 Then
            If TypeOf store(1) Is Class2 Then
                test(CType(store(0), Class2), CType(store(1), Class2))
            ElseIf TypeOf store(1) Is Class3 Then
                test(CType(store(0), Class2), CType(store(1), Class3))
                'and so on...
            End If

        ElseIf TypeOf (store(0)) Is Class3 Then
            'relevant tests of store(1)
        ElseIf TypeOf (store(0)) Is Class4 Then
            'relevant tests of store(1)
        End If

        Console.ReadLine()
    End Sub

    Sub test(cA As Class2, cB As Class2)
        Console.WriteLine(cA.class2SecondUniqueProperty)
        Console.WriteLine("2 and a 2")
    End Sub
    Sub test(cA As Class2, cB As Class3)
        Console.WriteLine("2 and a 3")
    End Sub
    Sub test(cA As Class2, cB As Class4)
        Console.WriteLine(cB.class4UniqueProperty)
        Console.WriteLine("2 and a 4")
    End Sub
    Sub test(cA As Class3, cB As Class2)
        Console.WriteLine("3 and a 2")
    End Sub
    Sub test(cA As Class3, cB As Class3)
        Console.WriteLine("3 and a 3")
    End Sub
    Sub test(cA As Class3, cB As Class4)
        Console.WriteLine("3 and a 4")
    End Sub
    'and so on, for many (but not all) pairs of classes inherited from Class 1.
    Public Class Class1
    End Class
    Public Class Class2
        Inherits Class1
        Property class2UniqueProperty As String = "only present in Class 2"
        Property class2SecondUniqueProperty As String = "only present in Class 2"
        Sub class2UniqueSub()
            'do something that the other classes derrived from Class1 don't
        End Sub
    End Class
    Public Class Class3
        Inherits Class1
        Property class3UniqueProperty As String = "only present in Class 3"
    End Class
    Public Class Class4
        Inherits Class1
        Property class4UniqueProperty As String = "only present in Class 4"
    End Class
    'will be more than 4 classes
End Module

编译器选择重载方法。您可能正在寻找一种在运行时选择方法的方法。您的类型匹配方法可以是一种解决方案,但最好将类型解析代码放在
test
方法中

从面向对象编程的角度来看,您的代码并不好。更好的方法是在类中定义一个方法并调用它

Public MustInherit Class Class1
  Public Property TypeNumber as  integer
  Public MustOverride Sub Test(Ca As Class1)
  Public MustOverride Sub SomeMethod()
End Class
Public Class Class2
  Inherits Class1
  Public Sub New()
       TypeNumber = 2
  End Sub

  Property class2UniqueProperty As String = "only present in Class 2"
  Public Overrides Sub Test(Ca As Class1)
      Ca.SomeMethod()
      Console.Writeln(Me.TypeNumber & " and a " & Ca.TypeNumber)
  End Sub
  Public MustOverride Sub SomeMethod()
      Console.Writeln(class2UniqueProperty)
  End Sub
End Class
“。。。继续学习其他课程

现在呼叫使用

store(0).Test(Store(1))

如果没有类型匹配逻辑,可能无法解决问题,但通常最好避免它。面向对象模式通常比使用模块方法更易于管理

谢谢你的回复。我完全同意我的示例代码是糟糕的OOP。据我所知,您的建议不允许我使用argument类中的任何方法或访问任何属性(因为它将被视为其静态类Class1),这是一个问题。这似乎是一个单一的调度解决方案,我认为在这里不起作用。这就是说,您的代码让我意识到某种双重分派解决方案可能不像我最初认为的那样混乱。我承认该解决方案并不总是可用的,但我认为您忽略了重写-方法在基类(class1)中定义,但执行代码在派生类(class2)中,并且可以访问其成员。因此,如果为参数类定义一个统一的接口,就可以访问它们的属性。我对重写的概念有一些理解,并在本程序的其他地方使用它。我只是重读了我的评论,我想也许我不清楚为什么我认为这个解决方案在这里不起作用。当我谈到argument类时,我指的是在代码中作为测试函数的参数提供的类的实例。您使用的重写方法允许我使用对象类的方法和函数,但不允许使用参数类。(由于字符限制,下面继续)因此,我可以键入:
store(0)。Test(store(1))
。在测试函数中,我可以使用属于存储(0)的动态(运行时)类的函数/属性(这很好),但我只能使用存储(1)的静态(编译时)类的函数/属性,而不是其动态类的函数/属性,这就是我需要的,这是一个完整的解决问题的办法。