显式运算符重载 + 继承
本文关键字:继承 重载 运算符 | 更新日期: 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
的每个子类覆盖该方法。 X
,Y
和 Z
应该派生自此解决方案的互基类,因此强制转换运算符可以将该基类作为结果类型。
public abstract class A
{
protected abstract W ConvertToW();
public static explicit operator W(A a)
{
return a.ConvertToW();
}
}
在此示例中,W
是 X
、 Y
和 Z
的基类。
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();
}
}