Как я понимаю, вы хотите добиться того, чтобы различные объекты могли сталкиваться друг с другом, и когда такое столкновение происходит, участники будут знать, с каким другим видом объектов они столкнулись.
Чтобы достичь этого, не используя рефлексию (или, как вы говорите, RTTI, хотя это термин C ++), рекомендуется использовать шаблон Visitor. Что вы сделали неправильно, так это то, что в этом сценарии оба объекта будут действовать как акцептор и как посетитель, в зависимости от того, с кем столкнулся, с каким. Объект, с которым мы сталкиваемся с , будет являться акцептором («принимает сталкивающийся объект»), а объект, с которым сталкивается с другим, становится посетителем («посещает / сталкивается с объект-акцептор).
Роли акцептора и посетителя могут быть изменены на противоположные, когда сталкивающийся объект является другим (движущийся астероид сталкивается с космическим кораблем или движущийся космический корабль сталкивается с неподвижным астероидом). Из этого примера вы можете видеть, что один объект может выступать в роли акцептора или посетителя в зависимости от случая. Это должно быть отражено в иерархии классов, поэтому оба объекта должны реализовывать интерфейс ICollidable и IVisitor.
Я переписал код, который вы выложили, поэтому классы Asteroid и Spaceship реализуют два интерфейса. Дополнительные классы посетителей больше не нужны, потому что наши объекты сами стали посетителями:
interface ICollidable
{
void Accept(IVisitor other);
}
interface IVisitor
{
void VisitAsteroid(Asteroid a);
void VisitSpaceship(Spaceship s);
}
class Asteroid : ICollidable, IVisitor
{
public void Accept(IVisitor other)
{
Console.Write("[Asteroid] ");
other.VisitAsteroid(this);
}
public void VisitAsteroid(Asteroid a)
{
Console.WriteLine("Collided with asteroid");
}
public void VisitSpaceship(Spaceship s)
{
Console.WriteLine("Collided with asteroid");
}
}
class Spaceship : ICollidable, IVisitor
{
public void Accept(IVisitor other)
{
Console.Write("[Spaceship] ");
other.VisitSpaceship(this);
}
public void VisitAsteroid(Asteroid a)
{
Console.WriteLine("Collided with spaceship");
}
public void VisitSpaceship(Spaceship s)
{
Console.WriteLine("Collided with spaceship");
}
}
class Main
{
public static void Main(string[] args)
{
Asteroid a1 = new Asteroid();
Asteroid a2 = new Asteroid();
Spaceship s1 = new Spaceship();
Spaceship s2 = new Spaceship();
s1.Accept(a1);
s1.Accept(as);
a1.Accept(s1);
a2.Accept(a2);
}
}
И если вы запустите программу, вы получите следующий вывод в консоли:
[Spaceship] Collided with asteroid
[Spaceship] Collided with spaceship
[Asteroid] Collided with spaceship
[Asteroid] Collided with asteroid
Надеюсь, вам стало ясно, как использовать шаблон Visitor для такого рода сценариев.