与基类中相同的方法名,在派生类中具有不同的返回类型

时间:2013-03-11 08:27:31

标签: c#

使用以下代码。

class Program
{
    static void Main(string[] args)
    {
        BaseClass obj = new BaseClass();
        DerivedClass obj2 = new DerivedClass();

        var x = obj.Method(2);
        var z = obj2.Method(1);
    }
}

class BaseClass
{
    public int Method(int i) { return i; }
}

class DerivedClass : BaseClass
{
    public string Method(int i) { return i.ToString(); }
}

为什么当我在派生类中使用该方法时,派生类对象正在调用它自己的函数,如果我没有它,派生类对象是否正在调用基函数?

4 个答案:

答案 0 :(得分:1)

如果要覆盖此行为,则可以使用new modifier标记一个方法,该方法将明确隐藏您派生自的类中的成员。

public new string Method(int i) { return i.ToString(); }

答案 1 :(得分:0)

您应该收到编译器关于此的警告。您的新Method()方法隐式隐藏基础(您可以使用new关键字将其显式化,这也会使编译器警告静音)。另请参阅http://msdn.microsoft.com/en-us/library/aa691135%28v=vs.71%29.aspx

请注意,在C#中,没有基于其输出类型重载方法的事情。仅仅因为你的新方法碰巧返回string并没有使它的签名与基础的任何不同。

请注意以下关于隐藏危险的警告,这也可能有助于说明发生的事情:

static void Main(string[] args)
{
    BaseClass obj = new BaseClass();
    DerivedClass obj2 = new DerivedClass();

    var x = obj.Method(2); //returns 2
    var z = obj2.Method(1); //returns 2 (2*2)
    var a = ((BaseClass)obj2).Method(1); //returns 1 (base's implementation!)
}

class BaseClass
{
    public int Method(int i) { return i; }
}

class DerivedClass : BaseClass
{
    public int Method(int i) { return i * 2; }
}

这与不同,以下代码中的行为会增加新的Method(string)重载:

static void Main(string[] args)
{
    BaseClass obj = new BaseClass();
    DerivedClass obj2 = new DerivedClass();

    var x = obj.Method(2); //returns 2
    var z = obj2.Method("1"); //returns "1"
    var a = ((BaseClass)obj2).Method("1"); //returns "1"
}

class BaseClass
{
    public int Method(int i) { return i; }
}

class DerivedClass : BaseClass
{
    public string Method(string s) { return s; }
}

答案 2 :(得分:0)

继承意味着您的DerivedClass会自动拥有BaseClass拥有的所有成员。因此,它还有Method,返回int

DerivedClass中引入一个具有相同名称和相同参数的新方法是个坏主意。因为DerivedClass有两个具有相同签名的方法。这就是你从编译器收到警告的原因。即使使用new关键字的修饰符时警告消失,使用两个具有相同签名的方法仍然是个坏主意。

相反,DerivedClass中的方法选择未使用的名称

更直接地回答您的问题:当您只有一个方法Method时,您在BaseClass内编写的方法一切都很好。 DerivedClass 继承此方法。这就是你可以在obj2上调用它的原因。但是当你在DerivedClass中引入第二种方法时,调用obj2.Method(1);需要在两种方法之间进行选择,因为不幸的是,有两种方法具有相同的签名。这种情况下的规则是选择DerivedClass中定义的方法。但请注意,这是编译时类型。所以如果你说

BaseClass obj3 = new DerivedClass();
var w = obj3.Method(42);

即使运行时类型obj3DerivedClass,它也是第一个因编译时类型而被调用的方法。就像我说的那样,obj3拥有两种方法。

答案 3 :(得分:0)

这是因为,您在派生类中隐藏了基本方法,并且在创建派生类的对象时,它将调用自己的实现。当你没有适当的机制(通过使用new关键字)时,编译器会大声喊叫,当你在派生类中没有方法时,基类实现就会启动。