none
为什么 基类的虚属性 在子类中重写时 无法修改 访问级别? RRS feed

  • 问题

  • 假设 基类 有个 虚属性 如下

    public virtual string Name{set;get;}

     

    子类重写该属性时

    public override string Name{private set;get} //是不允许的?

    public override string Name{get;}//这样缺允许呢? 如果我们可以直接重写子类属性 让其 之都 那么 我重写让其 set方法只能在 子类内部 设置 为什么不可以呢?没有道理呀...过不了编译...


    -_-!
    2010年4月22日 12:30

答案

  • 你好!

    重写是不能更改修饰符的。那么如何达到你的效果呢?下面的示例使用了 new 来隐藏父类的 Name 属性。

     

    public class A
    {
      public virtual string Name
      {
        get;
        set;
      }
    }
    
    public class Aex : A
    {
      // 隐藏父类的 Name 属性
      public new string Name
      {
        get { return base.Name; }
        private set { base.Name = value; }
      }
    }

     


    知识改变命运,奋斗成就人生!
    2010年4月22日 13:14
    版主
  • 1。

    override 是不能改 access modifier 的,假如可以更改,那么如何保证面向接口面向基类的契约一致呢?看看下面的代码

    public class Person { public virtual string Name { get; set; } }
    public class Employee : Person { public override string Name { private get; set; } }

    Person person = new Employee("Mr. Wang");
    string name = person.Name;  // 这里父类、子类就不一致了,Employee.Name 相对其基类的 Person.Name 可见性低,那么 person 的消费者怎么办,接口是 public 实现却是 private ?

    2。 关于 new 修饰符,当你使用的时候,一定要记住它是改变了运行时"多态” 的行为,实际上也破坏了上面的面向接口面向基类的特性,如果稍不注意运行时就出现莫名其妙的问题


    问题要简单,错误须详细@错误/异常/堆栈信息+操作系统+软件版本+all the context of the issue Hope Helpful | http://www.leoworks.net
    2010年4月22日 13:30

全部回复

  • C#没有虚属性这种说法。

    c#绝对有 我不知道他叫不叫虚属性 但事实上 属性前面 加 virtual 关键字 则 该属性的 行为和 虚方法完全一样

    这在协变 逆变 中可以充分的体会到...    和 new 关键字 隐藏属性 的行为 完全不一样.


    -_-!
    2010年4月22日 13:09
  • 汗,我才把那句话删除了你就引用了,速度快啊。问题是出在public override string Name{private set;get}上么?不过好像没有“虚属性”的说法。
    • 已编辑 络绎 2010年4月22日 13:13 Add more details
    2010年4月22日 13:12
  • 你好!

    重写是不能更改修饰符的。那么如何达到你的效果呢?下面的示例使用了 new 来隐藏父类的 Name 属性。

     

    public class A
    {
      public virtual string Name
      {
        get;
        set;
      }
    }
    
    public class Aex : A
    {
      // 隐藏父类的 Name 属性
      public new string Name
      {
        get { return base.Name; }
        private set { base.Name = value; }
      }
    }

     


    知识改变命运,奋斗成就人生!
    2010年4月22日 13:14
    版主
  • 你好!

    重写是不能更改修饰符的。

     


    知识改变命运,奋斗成就人生!
    您好。我想知道不允许更改修饰符的 设计初衷是什么? 既然允许 你在重写时 吧属性的 set或get去掉 为什么不允许 修改它的访问级别呢? 难以理解这样做的道理...所以有此一问

    -_-!
    2010年4月22日 13:21
  • 汗,我才把那句话删除了你就引用了,速度快啊。问题是出在public override string Name{private set;get}上么?不过好像没有“虚属性”的说法。

    你好!

    是有虚属性的。


    知识改变命运,奋斗成就人生!
    2010年4月22日 13:23
    版主
  • 汗,我才把那句话删除了你就引用了,速度快啊。问题是出在public override string Name{private set;get}上么?不过好像没有“虚属性”的说法。
    谢谢您...可能是我的叫法 让您迷惑了 确实 虚属性这个叫法 是我自己起的..... 不过不叫虚属性那应该叫什么呢? 疑惑中...

    -_-!
    2010年4月22日 13:23
  • 汗,我才把那句话删除了你就引用了,速度快啊。问题是出在public override string Name{private set;get}上么?不过好像没有“虚属性”的说法。
    谢谢您...可能是我的叫法 让您迷惑了 确实 虚属性这个叫法 是我自己起的..... 不过不叫虚属性那应该叫什么呢? 疑惑中...

    -_-!

    嗯,是我错了,原来还真叫虚属性。学习了。
    2010年4月22日 13:27
  • 1。

    override 是不能改 access modifier 的,假如可以更改,那么如何保证面向接口面向基类的契约一致呢?看看下面的代码

    public class Person { public virtual string Name { get; set; } }
    public class Employee : Person { public override string Name { private get; set; } }

    Person person = new Employee("Mr. Wang");
    string name = person.Name;  // 这里父类、子类就不一致了,Employee.Name 相对其基类的 Person.Name 可见性低,那么 person 的消费者怎么办,接口是 public 实现却是 private ?

    2。 关于 new 修饰符,当你使用的时候,一定要记住它是改变了运行时"多态” 的行为,实际上也破坏了上面的面向接口面向基类的特性,如果稍不注意运行时就出现莫名其妙的问题


    问题要简单,错误须详细@错误/异常/堆栈信息+操作系统+软件版本+all the context of the issue Hope Helpful | http://www.leoworks.net
    2010年4月22日 13:30
  • 1。

    override 是不能改 access modifier 的,假如可以更改,那么如何保证面向接口面向基类的契约一致呢?看看下面的代码

    public class Person { public virtual string Name { get; set; } }
    public class Employee : Person { public override string Name { private get; set; } }

    Person person = new Employee("Mr. Wang");
    string name = person.Name;  // 这里父类、子类就不一致了,Employee.Name 相对其基类的 Person.Name 可见性低,那么 person 的消费者怎么办,接口是 public 实现却是 private ?

    2。 关于 new 修饰符,当你使用的时候,一定要记住它是改变了运行时"多态” 的行为,实际上也打破了上面的面向接口面向基类的特性


    问题要简单,错误须详细@错误/异常/堆栈信息+操作系统+软件版本+all the context of the issue Hope Helpful | http://www.leoworks.net

    我终于明白了 感谢 您. 之前之所以困扰 来自下面的代码...

       public class Person { public virtual string Name { get{return "基类的Get"}; set; } }
        public class Employee : Person {
            string _Name;
            public override string Name { set { _Name = value; } }
        }

    Person person = new Employee("Mr. Wang");

    string name = person.Name;   // 我想当然的认为这里 会在运行时报错.... 但是显然 这里 name的值是 "基类的Get"

    事实证明 我错了.. 我 以前以为 属性 的本质 是一个方法 现在看来完全错了 属性的本质 分明是 两个方法 一个是get 一个是set.

    所以如上面这段代码...虽然子类重写了 基类的属性 并 吧get 去掉了 但是 子类会继承父类的 Name属性的Get方法 所以 去掉 即继承.

    也就是说 重写属性 我们可以选择 重写 get 或set 而不能把他们看成一个整体... 

    所以这里 修改某一个的访问修饰符 是不被允许的 。。。完全没有涉及上的 缺陷.... 感谢大家的帮助 .我完全理解了


    -_-!
    2010年4月22日 13:45
  • 1。

    override 是不能改 access modifier 的,假如可以更改,那么如何保证面向接口面向基类的契约一致呢?看看下面的代码

    public class Person { public virtual string Name { get; set; } }
    public class Employee : Person { public override string Name { private get; set; } }

    Person person = new Employee("Mr. Wang");
    string name = person.Name;  // 这里父类、子类就不一致了,Employee.Name 相对其基类的 Person.Name 可见性低,那么 person 的消费者怎么办,接口是 public 实现却是 private ?

    2。 关于 new 修饰符,当你使用的时候,一定要记住它是改变了运行时"多态” 的行为,实际上也破坏了上面的面向接口面向基类的特性,如果稍不注意运行时就出现莫名其妙的问题


    问题要简单,错误须详细@错误/异常/堆栈信息+操作系统+软件版本+all the context of the issue Hope Helpful | http://www.leoworks.net


    想请教一个问题,有没有办法实现一个类或类系(包括基类和继承类)对不同的访问者提供不同的访问级别。

    比如有 VisitorA 和 VisitorB, 对于 ClassA的属性Name, 有没有办法做到对VisitorA可读写,对VisitorB只读。(VisitorA和VisitorB可能继承自同一个类,但肯定处于不同的程序集)

    排除使用继承类new一个新Name属性的方法(那等于重新实现一次了),我的目的是想在复用ClassA的基础上实现这个功能,谢谢!

    补充一下提出这个问题的环境:一个管理系统,基础数据对象是公共的,希望数据对象对于不同层级的程序(程序集)提供不同的访问权限

    补充:终于找到解决方案了=> internal set + 友元程序集

    2010年11月12日 23:46