我在C#中有一个基类,如:
public class A{
public A something() {
//...
}
}
派生类如:
public class B:A
当我这样做时:
B obj = new B();
obj = obj.something();
VS抛出错误说(例如)“A无法转换为B”。是不应该返回B而不是A?
更新 谢谢大家。
我已经改变了A.something(字符串),现在是A.something(int)。传递给它的值总是整数,所以...... B(以及其他“姐妹”类)只是代码完全重构的中间步骤,因此它们将消失。
案例是我有4个班级做同样的事情,我正在改变一个统一的班级。因此,现在需要返回“B”对象。
答案 0 :(得分:0)
VS抛出错误说(类似)“A无法转换为 B“。它不应该返回B而不是A吗?
因为您的父类函数something()
返回类型为A
,并且您正尝试将其保存在Child类引用变量obj
中,如下所示:
obj = obj.something(); //something returns instance of `A`
这里子类引用变量obj
不能指向父类实例,但是其他方式(父类引用变量可以指向子类实例)是可能的。
答案 1 :(得分:0)
您应该考虑更改A类中something()
方法的返回类型。
它应该返回void
如果您需要在函数中修改参数,可以通过引用传递参数
这样,您可以重载/覆盖派生类中的方法,以便在需要时获得不同的行为。
现在它看起来的方式除了reinterpret_cast之外你没有什么可做的,这会在以后引起问题。
答案 2 :(得分:-1)
不,即使它在基类中定义,返回类型也不会有所不同,它仍然会返回A
的实例,它不一定可以转换为B.你可以这样做:
public class A{
public virtual A something() {
//...
}
}
public class B:A
{
public override A something() {
return new B();
}
}
B obj = new B();
obj = obj.something() as B;
当然,覆盖在这里并没有真正解决任何问题。你可以在基类中返回一个B
,它会以同样的方式工作,但这只是尴尬。
我认为您的问题是您没有遵循LISKOV替换原则:您应该能够使用实现A
的实例替换A
的每个实例,而不会影响客户端。一般来说,向下转换是一种代码气味。您应该将所有实例视为A
,并改变子类中的行为,而不是客户端中的行为
答案 3 :(得分:-2)
您必须覆盖B类中的Something()或获取obj.something()的结果;在A类的对象中。