0

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?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Gravitate
  • 2,885
  • 2
  • 21
  • 37
  • 1
    Change method parameter, it should take Shape object, instead of Concrete child (C#) – opewix Oct 23 '12 at 06:36
  • #2 I am sorry you had trouble understanding the question. I actually thought "Child Objects" and "Derived Classes" were more or less the same thing. Perhaps you would be kind enough to explain the difference between the two and which you think I should be using in this particular case? I only created the "Shape" class to group the shapes together so that I could use `Dim MyShape as Shape` to cover all the possible shapes. – Gravitate Oct 23 '12 at 17:29
  • @JesseJames ATM I am actually using an overloaded method which does different things depending upon two shapes passed to it. For example if I pass a circle and a triangle, it will actually call a different method than if I passed two circles. I am sorry, I just tried to simplify the situation to make the question easier to understand. – Gravitate Oct 23 '12 at 17:32
  • @Gravitate I tend to understand a *child object* as an association. While a *derived class* is a class that inherits a base class. – Matías Fidemraizer Oct 23 '12 at 17:39
  • @MatíasFidemraizer Is there any functional difference? A "child object" can access its "parents" properties just like a derived class can access its base properties can't it? I suppose you can reference a child by using "Parent.Child" but you can't do the same for "Base.Derived". There must be more fundamental differences that that... I shall have to ask the all knowing google :) – Gravitate Oct 23 '12 at 17:54
  • @Gravitate YES, there's a huge difference. ASSOCIATION isn't INHERITANCE! – Matías Fidemraizer Oct 23 '12 at 17:57
  • For those that are interested I asked a question about Parent/Child vs Base/Derived here: http://stackoverflow.com/questions/13037026/what-is-the-difference-between-a-child-of-a-parent-class-and-the-derived-of-a-ba/13037152. It turns out that the "Parent/Child" terms are generic and can be used in any situation to describe a hierarchy. Base/Derived specifically refer to inheritance. – Gravitate Oct 23 '12 at 19:51

2 Answers2

1

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.

Amiram Korach
  • 13,056
  • 3
  • 28
  • 30
  • Hi, Thank you for your input. This would solve the problem for me, however, I simplified the situation somewhat to make it easier to understand. The methods I am actually using is overloaded and accepts 2 "shapes". So if I pass (Circle, Circle), it does something different to if I pass (Circle, Triangle). I am sorry I didn't make this clear in the question. I shall update it now. – Gravitate Oct 23 '12 at 17:37
  • What exactly this method do? Is it combining the shapes or doing one thing on each? – Amiram Korach Oct 23 '12 at 19:01
  • well its a collision detection library (almost). I assign a shape to each object (say a triangle to a spaceship and a circle to a planet). Then pass the two shapes to the method. It then checks if the shapes intersect. Obviously, the method of checking intersection will vary depending on the type of shapes passed to it. I would just like the "shape" to be stored in the same variable on all my objects. Am I going about it the wrong way? Cos it feels like I am but can't think of an alternative. – Gravitate Oct 23 '12 at 19:24
  • OK, I have just updated the question. I hope it makes sense what I am trying to do now. – Gravitate Oct 23 '12 at 20:37
0

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
Damir Arh
  • 17,637
  • 2
  • 45
  • 83
  • Thanks, but I get an error - Circle is a type and cannot be used as an expression... that is why in my question, I compared Myshape.GetType and GetType(Circle), which does work... but it just doesn't seem the right way to do it. – Gravitate Oct 23 '12 at 17:57
  • @Gravitate Sorry about that. I'm not all that fluent in VB, that's why my code was influenced by C#. I fixed the code now and expanded on the explanation. – Damir Arh Oct 24 '12 at 19:04
  • 1
    Thanks, but that is basically the same as I suggested in the question, just checking the types in a different way. I was hoping for a better way but I am not sure there is one. I think I will need to just go with it or do a lot of re-structuring, although I am not sure how. BTW have you seen this: http://www.developerfusion.com/tools/convert/csharp-to-vb/? It is excellent for converting between vb and c#. – Gravitate Oct 24 '12 at 20:07
  • @Gravitate I don't know of any nicer approach you could take to do this. If you manage to find it, post it here so that others can see it. And thanks for the link: I don't know about it and it might come in handy. – Damir Arh Oct 24 '12 at 20:20