在子类中更改私有变量

时间:2019-08-29 17:52:19

标签: c# protection levels

我知道私有保护级别旨在阻止任何孩子访问私有父变量。

但是没有办法使用访问器和修改器(获取并设置)吗?我必须采用某种方式来更改私有字符串,因为这是家庭作业。

我有一个公共抽象宠物课,其中有一个私有字符串来命名。我想创建一条狗并使用该字符串名称。不过我不知道。既然是家庭作业,我知道我无法获得代码或其他任何信息,但是有人可以指出执行此操作的方法,以便我可以在Google上搜索吗?我所有的搜索都暗示这是不可能的。

这是我的代码,如果有帮助的话。

修改 我不能只是保护它。

public abstract class Pet
    {

        private string name;
        private string species;

        public abstract void speak();
        public abstract void play();
        public abstract void info();

    }

部分幼犬课程...

 class Dog : Pet
    {

        public Dog(string xname, string xspecies)
        {
            this.name = xname; // this is where I'm having trouble.
        }                     

2 个答案:

答案 0 :(得分:5)

让我们确保您具有清晰准确的理解;许多初学者被教会了一些微妙的错误。

  

我知道私有保护级别旨在阻止任何孩子访问私有父变量。

这是功能意图的正确摘要。基本上,您是说访问控制修饰符用于控制访问,这不足为奇。

但是,我想在这里指出两个细微之处。

首先,访问修饰符控制对事物名称的访问,而不是对事物的访问。当您有一个名为foo的成员时,名称foo只能用于从该成员的可访问性域中引用该成员 。 “可访问性域”是程序文本的区域;私有成员的可访问域是声明成员的类型的文本

如果您想出某种 other 方式来引用成员,则该机制不受辅助功能修饰符的控制。可访问性修饰符控制的唯一内容是,其中名称可以在程序文本中使用

确保头脑清晰。

第二,您注意到private成员不可被“子”访问,我假设您的意思是派生类。 在某些情况下,派生类可以按名称访问私有成员。鉴于我到目前为止所说的,您应该能够推断出它是什么。思考一下,然后继续阅读。



我说过,私有成员只能通过声明类型的文本内的名称进行访问,因此,如果私有成员可以通过派生类的名称进行访问,则派生类必须位于声明文本的内部输入

class Base
{
  private static int x;
  class Derived : Base
  {
      static void M() { Console.WriteLine(Base.x); } 
  }
}

这是合法的,因为x在其可访问性域内按名称使用。

那么,您如何处理家庭作业问题?只有两种方法:

(1)将Dog放在Pet里面;任何Dog都可以访问Pet的所有私有成员。这是C#的“仅适用于高级玩家”功能,几乎可以肯定不是您的教练正在寻找的功能。但这是一项非常强大的技术,我会经常使用,因此在以后的工作中要牢记这一点;尤其是,当您了解“工厂模式”时,您可以从口袋里掏出一些知识,即将派生类放入基类中是使工厂模式正常工作的好技巧。

(2)为私有成员建立一些访问器机制,并使该访问器机制的名称受保护,内部或公开。

通常,您会使用属性。您可以使用C#中的只读访问器来创建属性,如下所示:

class Base
{
  private int x;
  public int X { get { return x; } }
}

或者,在更现代的C#版本中,您可以使用以下简短格式:

  public int X => x;

现在Base之外的代码不能按名称使用x,因为它在Base.x的可访问性域之外。但是X具有不受限制的可访问域,因此 可以在您喜欢的任何地方使用。

这是一个只读访问器。要创建写访问器,请添加一个setter:

  public int X 
  { 
    get { return x; } 
    set { x = value; } 
  }

请注意,设置员具有神奇的value名称,这是将分配给该属性的值。

还有其他方法来创建访问器,但这是迄今为止最常见的方法。


在查看您的代码时,还有其他几件事:

(1)

    public abstract void speak();
    public abstract void play();
    public abstract void info();

在C#中,公开方法应为PascalCasedLikeThis,而不是lowercase。这只是一个任意约定,使您更容易阅读代码。

(2)

为什么info无效返回?当然应该返回一些信息

(3)

 class Dog : Pet

您打算进一步继承Dog的子类吗?可能不是,因为它不是abstract。考虑将不打算将其子类标记为sealed的类,这样您就不必担心为安全继承而设计该类。

答案 1 :(得分:2)

我认为您正在寻找protected访问修饰符,这意味着该变量可以在其类 和派生类实例 中访问:

public abstract class Pet
{
    protected string name;
    protected string species;

    public abstract void Speak();
    public abstract void Play();
    public abstract void Info();
}

class Dog : Pet
{
    public Dog(string xname, string xspecies)
    {
        name = xname;
        species = xspecies;
    }

    // Implementation of Pet here
}
相关问题