【问题标题】:Not getting this Inheritance没有得到这个继承
【发布时间】:2014-02-26 13:00:45
【问题描述】:

为什么我无法访问 S 类方法?为什么我能够在 M 类中创建具有相同名称的方法?

public class S
{
    public S()
    {
    }

    public int myFunc(int a, int b)
    {
        return a + b;
    }
}

public class M:S
{
    public M()
    {
    }

    public string myFunc(int a, int b)
    {
        return (a + b).ToString();
    }
} 

public class Test
{
    public static void Main(string[] args)   
    {
         M mm = new M();
         mm.myFunc(1,2);   // Why I am not able to access S class myFunc
    }
}

【问题讨论】:

  • 为什么忽略编译器的警告信息?你认为它只是为了给编译器开发者一些事情做吗?

标签: c# oop inheritance


【解决方案1】:

这被称为member hiding。您可以通过强制转换引用来访问S 类方法:

public class Test 
{ 
    public static void Main(string[] args)
    { 
        M mm = new M(); 
        string x = mm.myFunc(1,2);     // calls M.myFunc
        int y = ((S)mm).myFunc(1,2);   // calls S.myFunc

        S ss = new M();
        int z = ss.myFunc(1,2);        // calls S.myFunc
    } 
}

定义派生类成员时应使用new modifier;否则,您将收到编译器警告。

编辑:注意成员隐藏不同于多态。在成员隐藏中,类成员在编译时根据引用的 已声明 类型解析。在我上面的例子中,ss 被声明为S,即使它实际上被分配了一个M 类型的实例。

要实现多态性,您需要在基类成员上指定virtual 修饰符,在派生类成员上指定override。因此,对虚拟成员的调用在运行时解析为实例的 实际 类型。但是,多态性不允许您更改返回类型,因此您不能在示例中使用它。

【讨论】:

    【解决方案2】:

    因为 c# 不会基于返回类型重载,仅基于名称和参数。所以 M 重载 S 并且 S 的 myFunc 变得无法访问。更改名称或参数。

    如果你将它转换为 S,你将失去 M 拥有的额外值

    【讨论】:

    • 我无法理解这一点。因为首先我继承了 S 类,所以它的方法应该在 M 类中可用,如果它可用,那么为什么我能够在 M 类中创建具有相同方法的方法。
    • 当你创建一个具有相同名称和参数的方法时,它会自动重载它。例如 S' 方法在 M 中变得不可访问。它隐藏了方法
    【解决方案3】:

    更改返回类型不会重载方法(你不能在一个类中拥有两个完全相同的方法,名称和参数相同,返回类型不同)。

    原因很明显——如何决定,调用哪一个?

    要重载某些东西,你必须有不同的参数。

    【讨论】:

      【解决方案4】:

      您将能够通过 base.myFunc(1,2); 访问它

      【讨论】:

      • 基础在 Main 方法中无法访问
      【解决方案5】:

      您需要像这样投射对象:

       (S(mm)).myFunc(1, 2); // now you acces the int returns.
      

      为了良好的实践,如果一个方法有不同的返回另一个,它们必须有不同的名称。

      【讨论】:

        【解决方案6】:

        因为

                public string myFunc(int a, int b)
        

        hiding

                public int myFunc(int a, int b)
        

        【讨论】:

          【解决方案7】:

          好吧,除了 GrooV 所说的之外,在 C# 中,您需要将基方法声明为“虚拟”,并将子类中的方法声明为“覆盖”,这样才能正确覆盖而不破坏多态性。 阅读这两页,它们将帮助您更好地理解:

          override (C# Reference)

          Is it possible to override a non-virtual method?

          【讨论】:

            猜你喜欢
            • 2011-05-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-10-12
            • 2011-08-18
            • 2022-01-16
            • 1970-01-01
            相关资源
            最近更新 更多