Gravitate
Gravitate

Reputation: 3064

Call a method that requires a derived class instance typed as base class in VB.NET or C#

I have two objects - "Spaceship" and "Planet" derived from a base "Obj". I have defined several classes - Circle, Triangle, Rectangle, etc. which all inherit from a "Shape" Class.

For collision detection purposes, I want to give Obj a "shape":

Dim MyShape as Shape

So that in "Spaceship" I can:

MyShape = new Triangle(blah,blah)

and in "Planet" I can:

MyShape = new Circle(blah,blah)

I have a method (overloaded several times) which checks for collisions between different shapes, for example:

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

AND

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

This works fine when I call the function using the derived classes, for example:

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

But when I call it using MyShape, I get an error because the method is being passed a "Shape" (rather than the derived type) which the method does not have an overload for.

I could solve it by doing something like:

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

But that seems messy. Is there a better way?

Upvotes: 0

Views: 1740

Answers (2)

Damir Arh
Damir Arh

Reputation: 17855

Polymorphism can't help you with that therefore you'll have to create a common method with both parameters of type Shape and then distinguish them inside it:

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

I would put this function along with all the specialized implementations doing the actual collision detection in their own class 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

Upvotes: 0

Amiram Korach
Amiram Korach

Reputation: 13286

A way around it is to insert MyActualFunction as a class member.

In Shape:

Public MustOverride Function MyActualFunction()
End Function

In Circle and Triangle:

Public Overrides Function MyActualFunction()
End Function

Then call it like that:

MyShape.MyActualFunction()

and this will know which function to call.

Upvotes: 1

Related Questions