在继承的类中向下转换在基类中声明的对象
本文关键字:基类 声明 对象 转换 继承 | 更新日期: 2023-09-27 18:07:03
我正在为一个API创建一个插件,并且在继承方面有问题。是否有一种方法来"自动"向下cast对象,在基类中声明,在继承自它的类?
我的类结构如下:abstract class MyPart
{
public Part modelObject;
...
}
class MyPlate : MyPart
{
public ArraList points; // from API
...
}
class Floor : MyPlate
{
...
}
Part
是一个API类,其类结构如下:
class Part
class Plate : Part
现在,在我的代码在MyPlate
和Floor
类我需要使用Plate modelObject
来访问它的方法。目前我通过向下转换modelObject
:
(modelObject as Plate).doSomething;
这有点作用,尽管我想使它更简单。然而,主要问题是,当我试图访问modelObject
的成员时,我无法将它们作为引用。例如,当我试图声明points
时,它不会引用modelObject.points
:
points = (modelObject as Plate).points;
points = null; // modelObject.points != null
是否有一种方法将变量声明为对modelObject
的引用,以便它们可以被操纵?
这实际上是两个问题。为什么你的分数不会被删除,这个问题已经有了答案。但为了完整起见,这里是总结:
删除具有
调用var points = (modelObject as Plate).points
时,复制了对modelObject
的points
对象的引用。对于points = null
,您只需删除(null)对modelObject
的points
的引用,但modelObject
仍然保留对points
的引用。
删除modelObject
对points
的引用,调用(modelObject as Plate).points = null
。
子类
下转换但是对于你的主要问题,如何在子类中自动向下转换对象。有两种方法可以做到这一点。方法隐藏和泛型:
方法隐藏
将方法或基类的其他成员隐藏起来,并为名称提供新的含义。这样,您就可以赋予子类成员另一种含义和另一种返回类型。要实现这一点,您应该将modelObject封装在一个属性中。你的代码应该是这样的:
abstract class MyPart
{
private Part modelObject;
public Part ModelObject
{
get { return modelObject; }
set { modelObject = value; }
}
...
}
class MyPlate : MyPart
{
public new Plate ModelObject
{
get { return base.ModelObject as Plate; }
set { base.ModelObject = value; }
public ArraList points; // from API
...
}
class Floor : MyPlate
{
...
}
注意,在子类中使用base.ModelObject
。这使您仍然可以访问基类ModelObject,尽管您已经为ModelObject赋予了新的含义。除了方法重写之外,您可以保留基类Member,并且只提供具有相同名称的另一种含义。
注意,这有一些含义。最重要的一点是,类不知道成员是否隐藏在子类中,这意味着,转换为基类的子类将始终运行基类功能。为了说明目的,请参阅下面的代码示例。
public class Base
{
public void Do()
{
Console.WriteLine("Base");
}
}
public class Sub : Base
{
public new void Do()
{
Console.WriteLine("Sub");
}
}
public class Program
{
public static void Main(string[] args)
{
Sub sub = new Sub();
Base base = sub;
sub.Do(); //prints Sub
base.Do(); //prints Base, even though it is the same object.
}
}
泛型另一方面,对于泛型,您可以使用类型参数对Plate的类型进行参数化(在示例中为
TPlate
)。这稍微复杂一点,但也是更干净的方式,因为子类化和强制转换没有像方法隐藏那样令人困惑的效果。
abstract class MyPart<TPart>
where TPart : Part //configure a type parameter
{
public TPart modelObject;
...
}
class MyPlate : MyPart<Plate> //TPlate is now of type Plate
{
public ArraList points; // from API
...
}
class Floor : MyPlate
{
...
}
上面的例子不允许MyFloor进一步专门化类型参数,但这也可以实现:
abstract class MyPart<TPart>
where TPart : Part //configure a type parameter and force it to be a subclass of Part
{
public TPart modelObject;
...
}
class MyPlate<TPlate> : MyPart<TPlate>
where TPlate : Plate //force the type parameter to be a subclass of Plate
{
public ArraList points; // from API
...
}
class Floor : MyPlate<Floor> //TType is now Floor
{
...
}
您正在创建引用的副本。所以points
和(modelObject as Plate).points
指向相同的内存。当将null
赋值给points
时,会清除一个引用。另一个仍然存在。
如果您希望(modelObject as Plate).points;
为空。直接使用:(modelObject as Plate).points = null;
当您将points
设置为null
时,您将取消作用域中名为"points"的引用,而不是实际变量。如果你真的不想只做modelObject.points = null
(你通常只做CC_32),你想通过ref来实际访问它。
见https://msdn.microsoft.com/en-us/library/14akc2c7.aspx
也就是说,我不确定你为什么要把对象向下投射,因为我们看不清这里发生了什么