你何时以及为什么要翻转一个物体?

时间:2011-01-11 09:05:53

标签: c# .net oop class casting

这被认为是向上倾斜吗?

Derived d = new Derived();
Base b = d; // Always OK.

为什么会有人上传?什么时候?是因为我们必须将对象转换为基类,因此它没有派生类的功能吗?

此代码在内存中的外观如何?派生类实例化并为该对象创建内存。然后创建一个基类对象,现在引用d

7 个答案:

答案 0 :(得分:9)

我想你可能会对上传的内容感到有些困惑。 upcast不会禁用派生对象的功能,也不会创建新的Base对象。相反,它只是对您所提升的对象进行更有限的视图。通过基类引用,您只能访问在Base中声明的那些方法,但如果在派生类中重写了这些方法中的任何一个,则通过基类引用调用它们仍将调用派生版本。

至于你何时想要这样做,看到人们因为没有特殊原因而被人上传的情况并不常见。毕竟,这限制了你可以对对象做的事情。但是,正如其他海报所指出的那样,在将对象传递给函数或从函数返回对象时隐式向上转换是很常见的。在这些情况下,upcast允许函数作者接受具有完成工作所需的最弱要求集的参数,或者从表现出某些行为的函数返回对象而不必显示完整类型的对象

答案 1 :(得分:3)

向上转换是正常的,因为每个Derived都是Base

当你编写一个继承自A类的B类时,B就是A的子类。这意味着你可以使用B 类型的对象,你可以使用一个对象A型。

你应该阅读inheritance以及它有多强大。

答案 2 :(得分:1)

如果你想使用polymorphism,你可以使用upcast,例如你有一个接受Base的方法,但你喜欢用Derived调用它:

public void DoAction(Base base)
{
 // do stuff
}

DoAction(drivedItem);

DoAction(baseItem);

以上两个电话都是真的。

但是在多态性中,你不能进行向下转换,你可以使用例如方法重载来克服你的问题。

答案 3 :(得分:1)

  

是否导致我们必须将对象转换为基类,因此它不具有派生类的功能?

因为有些代码无论您的对象是Derived1还是Derived2都能正常工作,并且只是基于它支持Base功能的假设而编写。这称为抽象,将导致代码重用。您不必分别为Derived1Derived2重写该功能。您抽象出特定于Derived1Derived2的详细信息。

顺便说一下,很多时候,你没有明确地进行演员表演。将实例传递给函数时,只需利用这一事实即可。例如,当您向string添加ArrayList时,您隐式将其强制转换为基类型object,因为Add的签名是:

void Add(object o);

答案 4 :(得分:0)

我不确定你经常编写类似你的例子的代码,但是这种类型的转换的一个应用是方法调用:

void Test()
{
   Derived d = new Derived();
   this.DoSomething(d);
}

void DoSomething(Base b)
{
   // something
}

在这种情况下,d不会“变成”Base对象,它只是被视为一个对象。我不确定,但我想与d对象相关的实际内存根本没有变化。

答案 5 :(得分:0)

关于你的第二个问题(它们在内存中的外观),它们在堆栈上看起来都是一样的。在堆栈上,它们都是堆的简单指针。

答案 6 :(得分:0)

Reason One :如果我在2008年编写了一个知道Base类的代码,并使用它来做一些只涉及该类功能的代码,那么upcasting可以让你创建{ 2011年的{1}}类,并将实例传递给我的代码而不做任何更改。

可以说,如果我首先使用泛型编写代码,这也可以完成(也许更强大)。

原因二:如果需要在单个容器中存储多个不同类的实例,则需要将这些实例向上转换为共享基类。例如,考虑一个“当前加载”数据源的列表,这些数据源可以是本地文件,URL,内存数据甚至套接字 - 所有这些都是共享公共数据源类的特定类。