显式运算符重载 + 继承

本文关键字:继承 重载 运算符 | 更新日期: 2023-09-27 18:37:25

我一直在考虑解决我遇到的问题的方法,但我不确定它是否有效。

假设我们有一个名为 A 的基类和 3 个子类 B、C 和 D。

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

此外,我们还有三个类 X、Y 和 Z。

在我的系统上,对象类型B,C,D

作为类型A传递,通常我必须将类型B,C,D的对象转换为对象X,Y或Z(这不是强制转换,我手动转换它们,因为它们完全不同)。

因此,要将对象类型 A 转换为类型 X、Y 或 Z,

我需要先检查子类型,然后根据子类型对 A 对象进行一些操作的结果初始化 X、Y 或 Z 对象。

我想过将显式强制转换操作从 A 重载到 X、Y 或 Z,只是执行与转换它们时相同的过程,但后来我想......是否有可能以某种方式使用 polimorfism 并从 B、C 和 D 重载强制转换,以至于当我添加 A 的新子类型时,我不需要更改 A 的转换代码?(只需将显式强制转换重载添加到新的子类型)

如果有什么令人困惑的事情,我希望我已经正确解释了自己。

注意:我将为 X,Y,Z 添加转换重载

显式运算符重载 + 继承

假设 X、Y 和 Z 派生自公共类型 T,在 A 中声明一个抽象转换方法

public abstract class A
{
    public abstract T Convert();
}
并在 B 中覆盖它以返回

X,在 C 中覆盖它以返回 Y,在 D 中覆盖它以返回 Z。这样,每个类型都负责返回自己的转换类型,并且在添加新类型时不会在 A 中进行任何更改。

你可以让类型A的强制转换运算符调用A实例的虚拟(或抽象?)实例方法,并为A的每个子类覆盖该方法。 XYZ 应该派生自此解决方案的互基类,因此强制转换运算符可以将该基类作为结果类型。

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

在此示例中,WXYZ 的基类。

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();
}

这让你在知道类是B时得到一个强类型结果(通过ConvertToX,因为X Convert()不能覆盖object Convert()),当你只知道它是一个A时,你会得到一个object。 由于显式转换只能基于您正在使用的变量的静态类型进行,因此没有像您问的那样使用强制转换来做到这一点的好方法。


(@svick指出了我以前的代码中的一个主要缺陷,如下所示,即如果您只知道对象是A,而不是A<T>,则无法轻松使用它执行任何操作。 我会把它留在这里,以防你有任何用处:)

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
    }
}

如果你有一个可以转换为多种类型的类型,你可以这样做:

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

或:

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