【问题标题】:Is it possible to determine the type of a class at instantiation or convert the type afterwards without casting?是否可以在实例化时确定类的类型或在不强制转换的情况下转换类型?
【发布时间】:2020-10-11 12:23:13
【问题描述】:

例如:我有一些类都继承自同一个类。

Public Class MasterClass
    ' content
End Class

Public Class ClassA
  Inherits MasterClass
    'content
End Class
Public Class ClassB
  Inherits MasterClass
    'content
End Class
Public Class ClassC
  Inherits MasterClass
    'content
End Class

我想决定运行时我需要哪一个。然后我可以这样做:

Private myInstance As MasterClass
If conditionA Then
    myInstance = New ClassA
ElseIf conditionB Then
    myInstance = New ClassB
Else
    myInstance = New ClassC
End

但它可能会变得很长,而且我每次使用它时仍然必须投射它。

我可以将类型分配给变量,但我不知道如何使用该类型来创建该类型的新实例..

Dim storedType As Type = GetType(ClassA)
Dim someInstance = New storedType 'Does not work

有没有更好的方法?可以在运行时更改变量的类型吗?

【问题讨论】:

  • 创作部分是“工厂”。是的,如果您需要对其进行硬编码,它可能会变得很长。根据您要执行的操作,可能会有基于反射的方法可以实现,因此您无需为工厂可能返回的每个可能的类添加代码(如果您想这样做,这甚至可能是必要的有某种插件支持,这些插件将从第三方发布或以与您的主程序不同的节奏发布。

标签: vb.net class type-conversion typeconverter


【解决方案1】:

每次我使用它时我仍然必须投射它。

关于多态性和继承的想法是您不必必须强制转换它们才能使用它们。您可以以这样一种方式编写东西,即主类具有您需要的所有功能等(无论它们是否做任何事情),然后您调用事物就好像您只是在处理主类但是,因为每个孩子都实现了一个不同的行为,最终的结果是不同的——你的程序甚至可能不知道(如果子实现来自第三方 dll)发生了什么,但 没关系

你能在运行时改变变量的类型吗?

当然可以,但是您必须使用它的外观。 “如果我的对象是 x 的实例,则将我的对象转换为 x 并使用方法 X1,否则如果我的对象是 ay 则转换为 y 并调用 y1”的长链不是多态/没有正确利用继承原则 - 你是应该调用 myobject.whatever,如果我的对象是 x,则发生 x1,如果是 y,则发生 y1

我想决定运行时我需要哪一个

但是你不必在知道类 a/b/c 的类中这样做 - 每个类 a/b/c 都可以这样做,因此变得自给自足。您可以将所有实例放在父类型的数组中,并访问每个实例,询问它们是否处理条件并使用表示可以的实例

考虑一个比这个人为的 a/b/c 类比喻更好的现实世界示例:

您的任务是编写一个应用程序,该应用程序可以从某个位置(http 或 ftp 或磁盘位置)下载图像(png、jpg 或 gif)、旋转图像并将其上传到其他位置

您决定拥有一个指定 CanHandle 函数和 Rotate 函数的 ImageRotator 父级。它有 3 个子类,一个处理 jpg,一个旋转 gif,一个处理 png。当出现 PNG 文件名时,JpgRotator 会在被问及是否可以处理时说“否”等。

另外,您有一个可以处理并具有下载/上传功能的 FileMover 父级。同样,父母根本没有实现这些。这三个子类实现了上/下 http、ftp 和磁盘位置的能力

您创建每个旋转器的实例并将其放入 ImageRotator 类型的数组中。您还可以在作为 FileMover 父类型的数组上创建每个移动器的实例。

您的用户在 http url 中指定一个 jpg,并将其存储在最后的磁盘位置。你循环你的 FileMovers 并询问它们是否支持用户提供的位置。 http 移动器说是的,你调用它的下载到一个临时路径。然后你将他的路径传递给每个旋转器,jpg 旋转器说是,你调用旋转。最后,您寻找另一个可以处理本地磁盘输出路径的移动器...

有人决定使用插件 dll 扩展您的程序,该 dll 增加了将文件放入和取出 db 的能力,并支持 tiff 图像.. 忽略了他们的类的实例如何在您的数组中的魔力,您可以看到您的程序现在可以移动这些新位置和类型,因为它们是否处理 db/tiff 的逻辑不是您代码的一部分。您的代码只是一致地对待所有内容

【讨论】:

  • 那么您至少可以使声明更容易吗?大约有 20 多个子类,我已经在列表中列出了它们的类型。
  • 呃,是的..您可以使用 IOC 容器/DI,但老实说..这是 20 行代码,您只需要执行一次.. 就这样做! ps,检查我的答案的编辑
【解决方案2】:

在这种情况下接口是最好的选择

Interface ABC
    Property Text As String
    Property Value As Integer
End Interface
Public Class MasterClass

End Class

Public Class ClassA
    Inherits MasterClass : Implements ABC
    Property Mystr As String Implements ABC.Text
    Property Sum As Integer Implements ABC.Value
End Class
Public Class ClassB
    Inherits MasterClass : Implements ABC
    Property MyText As String Implements ABC.Text
    Property Value As Integer Implements ABC.Value
End Class
Public Class ClassC
    Inherits MasterClass : Implements ABC
    Property str As String Implements ABC.Text
    Property Value As Integer Implements ABC.Value
End Class

用法

Dim myABC As ABC
If conditionA Then
    myABC = New ClassA
ElseIf conditionB Then
    myABC = New ClassB
Else
    myABC = New ClassC
End If
myABC.Text = "Interface"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 2021-01-24
    相关资源
    最近更新 更多