【问题标题】:Call a method that requires a derived class instance typed as base class in VB.NET or C#调用需要在 VB.NET 或 C# 中作为基类类型的派生类实例的方法
【发布时间】:2012-10-23 06:31:17
【问题描述】:

我有两个对象——从基础“Obj”派生的“Spaceship”和“Planet”。我定义了几个类——圆形、三角形、矩形等,它们都继承自“形状”类。

出于碰撞检测的目的,我想给 Obj 一个“形状”:

Dim MyShape as Shape

所以在“宇宙飞船”中我可以:

MyShape = new Triangle(blah,blah)

在“星球”中我可以:

MyShape = new Circle(blah,blah)

我有一个方法(重载多次)检查不同形状之间的碰撞,例如:

public shared overloads function intersects(byval circle1 as circle, byval circle2 as circle) as boolean

public shared overloads function intersects(byval circle as circle, byval Tri as triangle) as boolean

当我使用派生类调用函数时,这很好用,例如:

dim A as new circle(blah, blah)
dim B as new triangle(blah, blah)
return intersects(A,B)

但是当我使用 MyShape 调用它时,我收到一个错误,因为该方法正在传递一个“Shape”(而不是派生类型),该方法没有重载。

我可以通过以下方式解决它:

Public Function Translate(byval MyShape1 as Shape, byval MyShape2 as Shape )as boolean
if shape1.gettype = gettype(circle) and shape2.gettype=gettype(circle) then ''//do circle-circle detection
if shape1.gettype = gettype(triangle) and shape2.gettype=gettype(circle) then ''//do triangle-circle detection
End Function

但这似乎很混乱。有没有更好的办法?

【问题讨论】:

  • 更改方法参数,它应该采用Shape对象,而不是Concrete child (C#)
  • #2 很抱歉您无法理解这个问题。我实际上认为“子对象”和“派生类”或多或少是一回事。也许您会很友好地解释两者之间的区别以及您认为我应该在这种特殊情况下使用哪个?我只创建了“Shape”类来将形状组合在一起,这样我就可以使用Dim MyShape as Shape 来覆盖所有可能的形状。
  • @JesseJames ATM 我实际上使用了一个重载方法,它根据传递给它的两个形状做不同的事情。例如,如果我传递一个圆形和一个三角形,它实际上会调用与传递两个圆形不同的方法。对不起,我只是试图简化情况以使问题更容易理解。
  • @Gravitate 我倾向于将 子对象 理解为关联。而派生类是继承基类的类。
  • @MatíasFidemraizer 有什么功能上的区别吗? “子对象”可以访问其“父对象”属性,就像派生类可以访问其基属性一样,不是吗?我想你可以通过使用“Parent.Child”来引用一个孩子,但你不能对“Base.Derived”做同样的事情。必须有更根本的区别......我将不得不问无所不知的谷歌:)

标签: c# .net vb.net class downcast


【解决方案1】:

解决方法是将MyActualFunction 作为类成员插入。

形状:

Public MustOverride Function MyActualFunction()
End Function

在圆形和三角形中:

Public Overrides Function MyActualFunction()
End Function

然后这样称呼它:

MyShape.MyActualFunction()

这会知道调用哪个函数。

【讨论】:

  • 您好,感谢您的意见。这将为我解决问题,但是,我稍微简化了情况以使其更容易理解。我实际使用的方法被重载并接受 2 个“形状”。因此,如果我通过 (Circle, Circle),它会做一些不同于我通过 (Circle, Triangle) 的事情。很抱歉,我没有在问题中说明这一点。我现在就更新。
  • 这个方法到底是做什么的?是结合形状还是对每个形状做一件事?
  • 它是一个碰撞检测库(几乎)。我为每个对象分配了一个形状(比如宇宙飞船的三角形和行星的圆形)。然后将这两个形状传递给该方法。然后它检查形状是否相交。显然,检查交叉点的方法将根据传递给它的形状类型而有所不同。我只想将“形状”存储在我所有对象的同一个变量中。我是不是走错了路?因为感觉就像我一样,但想不出替代方案。
  • 好的,我刚刚更新了问题。我希望我现在要做的事情是有意义的。
【解决方案2】:

多态无法帮助您解决此问题,因此您必须创建一个具有 Shape 类型的两个参数的通用方法,然后在其中区分它们:

Public Function DoCollide(ByRef shape1 As Shape, ByRef shape2 As Shape) As Boolean
    If TryCast(shape1, Circle) IsNot Nothing And TryCast(shape2, Circle) IsNot Nothing Then
        Return DoCollide(TryCast(shape1, Circle), TryCast(shape2, Circle))
    ElseIf TryCast(shape1, Circle) IsNot Nothing And TryCast(shape2, Triangle) IsNot Nothing Then
        Return DoCollide(TryCast(shape1, Circle), TryCast(shape2, Triangle))
    Else
        Return False
    End If
End Function

我会把这个函数和所有专门的实现一起放在他们自己的类中进行实际的碰撞检测CollisionDetector

Public Class CollisionDetector

    Public Function DoCollide(ByRef shape1 As Shape, ByRef shape2 As Shape) As Boolean
        If TryCast(shape1, Circle) IsNot Nothing And TryCast(shape2, Circle) IsNot Nothing Then
            Return DoCollide(TryCast(shape1, Circle), TryCast(shape2, Circle))
        ElseIf TryCast(shape1, Circle) IsNot Nothing And TryCast(shape2, Triangle) IsNot Nothing Then
            Return DoCollide(TryCast(shape1, Circle), TryCast(shape2, Triangle))
        Else
            Return False
        End If
    End Function

    Public Function DoCollide(ByRef circle1 As Circle, ByRef circle2 As Circle) As Boolean
        Return True
    End Function

    Public Function DoCollide(ByRef circle As Circle, ByRef triangle As Triangle) As Boolean
        Return True
    End Function

End Class

【讨论】:

  • 谢谢,但我得到一个错误 - Circle 是一种类型,不能用作表达式......这就是为什么在我的问题中,我比较了 Myshape.GetType 和 GetType(Circle),它确实工作......但这似乎不是正确的方法。
  • @Gravitate 对此感到抱歉。我对 VB 不是很流利,这就是我的代码受 C# 影响的原因。我现在修复了代码并扩展了解释。
  • 谢谢,但这与我在问题中建议的基本相同,只是以不同的方式检查类型。我希望有更好的方法,但我不确定有没有。我认为我将需要继续使用它或进行大量重组,尽管我不确定如何。顺便说一句,你见过这个:developerfusion.com/tools/convert/csharp-to-vb?它非常适合在 vb 和 c# 之间进行转换。
  • @Gravitate 我不知道你可以采取什么更好的方法来做到这一点。如果您设法找到它,请将其发布在此处,以便其他人可以看到。并感谢您的链接:我不知道它可能会派上用场。
猜你喜欢
  • 2019-07-25
  • 1970-01-01
  • 2016-07-06
  • 1970-01-01
  • 1970-01-01
  • 2014-03-22
  • 2014-09-05
  • 2018-11-03
  • 2021-05-23
相关资源
最近更新 更多