Mario Corchero
Mario Corchero

Reputation: 5575

Explicit operator overload + inheritance

I have been thinking about a way solve a problem I have and I'm not sure whether it will work or not.

Say we have a base class called A and 3 subclass B,C and D.

        A
        ^
-----------------
|       |       |
B       C       D

Also we have three classes X, Y and Z.

On my system objects type B,C,D are passed as type A and usually I have to convert the Objects of type B,C,D to either objects X,Y or Z (That's not a cast, I manually convert them since they are totally different).

Therefore, to convert an Object type A to a type X, Y or Z I need to check the subtype first and then initialize a X, Y or Z Object with the result of some operations about the A Object depending on the subtype.

I thought about overloading an explicit cast operation from A to X, Y or Z just doing the same process I was doing when I converted them, but then I thought... Would it be possible to use polimorfism and overload the cast from B,C and D in some way that when I add a new subtype of A I do not need to change the cast code of A?(Just add the explicit cast overload to the new subtype)

I hope I have explained myself properly sorry if there is something confusing.

NOTE: I will add a cast overload for X,Y,Z

Upvotes: 5

Views: 2116

Answers (3)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112392

Assuming that X, Y and Z derive from a common type T, declare an abstract conversion method in A

public abstract class A
{
    public abstract T Convert();
}

and override it in B to return an X, in C to return a Y and in D to return a Z. This way each type is responsible to return its own converted type and there is no change to make in A when a new type is added.

Upvotes: 3

Tim S.
Tim S.

Reputation: 56536

abstract class A
{
    public abstract object Convert();
}
class B : A
{
    public override object Convert()
    {
        return ConvertToX();
    }
    public X ConvertToX()
    {
        return new X();
    }
}
void SomeMethod()
{
    A o = new B();
    var result = (X)o.Convert();
}

This lets you have a strongly-typed result when you know that class is B, (through ConvertToX, since X Convert() can't override object Convert()) and an object when you only know it's an A. Since explicit conversions can only happen based on the static type of the variable you're using, there's not really a good way to do this using casting, like you asked.


(@svick pointed out a major flaw in my previous code, which is below, which is that you can't easily do anything with it if you only know the object is an A, not an A<T>. I'll keep it here in case you have any use for it:)

interface IConvertible<out T>
{
    T Convert();
}
abstract class A
{
}
abstract class A<T> : A, IConvertible<T>
{
    public abstract T Convert();
    public static explicit operator T(A<T> a)
    {
        return a.Convert();
    }
}
class B : A<X>
{
    public override X Convert()
    {
        // TODO implement this
    }
}

And if you have a type that can be converted to multiple types, you could do:

class B : A<X>, IConvertible<Y>
{
    public override X Convert()
    {
        throw new NotImplementedException();
    }
    Y IConvertible<Y>.Convert()
    {
        throw new NotImplementedException();
    }
}

Or:

class B : A, IConvertible<X>, IConvertible<Y>
{
    X IConvertible<X>.Convert()
    {
        throw new NotImplementedException();
    }
    Y IConvertible<Y>.Convert()
    {
        throw new NotImplementedException();
    }
}

Upvotes: 2

O. R. Mapper
O. R. Mapper

Reputation: 20730

You can have your cast operator for type A call a virtual (or abstract?) instance method of your A instance and override that for each subclass of A. X, Y and Z should derive from a mutual base class for this solution, though, so the cast operator can have that base class as a result type.

public abstract class A
{
    protected abstract W ConvertToW();

    public static explicit operator W(A a)
    {
        return a.ConvertToW();
    }
}

In this example, W is a base class of X, Y and Z.

Upvotes: 2

Related Questions