Ding Dong Ding Dong - 27 days ago 9
C# Question

How to not write dumb overloads but handle lots of casting in overloaded function

I would like to design something that gets the distance between two things. However, these things can be manifest in many obnoxious forms.

Let's say we have a set of classes. (Not necessarily base and derived)
Cat, CoolCat, ReallyCoolCat

All of them have a way to access a position. I would like to write a function call 'DistanceBetween' that gets the distances between the cats.

I can make overloads:

public static float DistanceBetween(Cat cat1, Cat cat2)
{
return Mathf.Abs(cat1.position - cat2.position);
}

public static float DistanceBetween(CoolCat cat1, CoolCat cat2)
{
return Mathf.Abs(cat1.transform.position, cat2.transform.position);
}

// ... etc...


However, then I would have cases where I need to know the distance between a Cat and a CoolCat or the distance between a CoolCat and a ReallyCoolCat. That means...

public static float DistanceBetween(Cat cat1, CoolCat cat2)
{
return Mathf.Abs(cat1.position, cat2.transform.position);
}

public static float DistanceBetween(CoolCat cat1, ReallyCoolCat cat2)
{
return Math.Abs(cat1.tranform.position, cat2.kittyVariables.position);
}

// ... etc ...


But then it just seems arbitrary cause I can rearrange the order of my arguments and my function wouldn't work. So I have to make...

public static float DistanceBetween(CoolCat cat1, Cat cat2)
{
return Mathf.Abs(cat1.tranform.position, cat1.position);
}

public static float DistanceBetween(ReallyCoolCat cat1, CoolCat cat2)
{
return Math.Abs(cat1.kittyVariables.position, cat2.transform.position);
}

// ... etc ...


So This means the amount of code per cute kitties I make grows by n^2. This amount of code growth is not acceptable due to how many cute kitties I want to make. I cannot implement inheritance because my cute kitties (though similar in name) have very different features and are unique. (I could add doggies and the such too.) So what I am thinking is to create an interface 'IDistanceable' that says the implementing class has a 'Position' property and implementing it in each kitty. But this starts to seem like overkill though, all I wanted was something that can rearrange my arguments and make Func(a,b) equal to Func(b,a)...

I don't really know what to do... both solutions (write 500 functions or make interface and lots of junk) both seem wrong.

The interface will NOT work due to the inability to modify some of the cute kitty classes...

Please help me and my cute kitties! Thanks!

Answer Source

If you can't modify the classes, you're best off wrapping them in something you can modify. That way, you can centralize the class-specific logic in one place (the different constructors).

class CatWrapper
{
    private int position { get; set; }

    public CatWrapper(Cat cat) { ... }
    public CatWrapper(CoolCat cat) { ... }
    public CatWrapper(ReallyCoolCat cat) { ... }

    public DistanceFrom(CatWrapper other) { ... }
}