【问题标题】:Override Base Class Static Variable覆盖基类静态变量
【发布时间】:2014-07-22 03:10:23
【问题描述】:

我正在尝试覆盖基类 const/static 变量。但我得到编译器错误:

“Arc.CLASS_NAME”隐藏了继承的成员“Element.CLASS_NAME”。使用 如果打算隐藏,则使用新关键字

有没有办法覆盖这种变量?也许我需要将数据类型更改为public virtual static readonly

public class Element {
    public const string CLASS_NAME = "___ELEMENT___";

    ...
}

public class Arc : Element {
    public const string CLASS_NAME = "___ARC___";

    // Problem is: CLASS_NAME needs to be const to be used as a default argument
    public Arc(uint nUTMZone=DEF_UTM_ZONE, string nName=CLASS_NAME) : base(nUTMZone, nName) {

    }
}

【问题讨论】:

  • 为什么不按照编译器的建议使用new
  • @MichaelLiu 当编译器消息显示hiding 我从逻辑上讲,将其解释为将变量设为私有(而不是覆盖,这是下面答案的真正含义),我需要这个变量公开。
  • “隐藏”并不意味着私密;这意味着它会影响基类中的 CLASS_NAME。根据您的编辑,您应该使用new
  • 你到底想在这里实现什么?

标签: c# inheritance


【解决方案1】:

不知道你的意思-

从逻辑上讲,将其解释为将变量设为私有(而不是覆盖,这正是下面答案的真正含义),我需要将此变量设为公开

这似乎是矛盾的,因为 -

  1. 如果你真的需要它作为公共的(我认为你指的是父类变量)那么覆盖它有什么意义呢?还是创建一个同名的变量?

  2. 如果您想使用同名变量之一覆盖变量,请使用new 或@Dmtry 提供的解决方案。但是使用new 有一个好处。您可以根据需要更改变量签名。比如下面是一段完美编译的代码——

    public class Element {
        public const string CLASS_NAME = "___ELEMENT___";
    
    }
    
    public class Arc : Element {
        private new readonly string CLASS_NAME = "___ARC___";
    }
    
  3. 当它们是实例变量时,即使变量隐藏了父变量,您仍然可以通过使用类型转换或基引用来引用父变量,如下所示 -

    public class Element
    {
        public string CLASS_NAME = "___ELEMENT___";
    
    }
    
    public class Arc : Element
    {
        public new string CLASS_NAME = "___ARC___";
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            Arc a = new Arc();
    
            Console.WriteLine(a.CLASS_NAME);
            Console.WriteLine((a as Element).CLASS_NAME);
    
            Console.ReadLine();
        }
    }
    
  4. 但是您再次使用static 变量,因此您可以访问它们的唯一方法是使用ClassName 因此覆盖点应该不是问题,因为您将始终通过类而不是通过实例访问,所以您将始终知道您使用的是哪个变量。-

    public class Element
    {
        public const string CLASS_NAME = "___ELEMENT___";
    
    }
    
    public class Arc : Element
    {
        public new const string CLASS_NAME = "___ARC___";
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            Arc a = new Arc();
    
            Console.WriteLine(Arc.CLASS_NAME);
            Console.WriteLine(Element.CLASS_NAME);
    
            Console.ReadLine();
        }
    }
    

【讨论】:

    【解决方案2】:

    不,你不能覆盖它;常量不是虚拟成员(编译器在编译过程中基本上会用常量的值替换常量)。

    如果您的意图是隐藏基类字段,则按照编译器的说明进行操作:添加 new 关键字:

    new public const string CLASS_NAME = "___ARC___";
    

    【讨论】:

    • 执行您的建议会给出以下编译器消息Unexpected symbol 'new' in class, struct, or interface member declaration
    • new 放在public 之前(或const 之前)。
    猜你喜欢
    • 1970-01-01
    • 2013-10-27
    • 2010-10-10
    • 1970-01-01
    • 1970-01-01
    • 2016-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多