Почему я не использую защищенную работу?

Я читал, что к защищенному члену можно получить доступ из производных классов, но следующее не работает.

class A
{
    protected int Test;
}
class B:A
{
    A instanceOfA= new A()

    public B()
    {
        instanceOfA.Test //Not possible
    }
}

person Miria    schedule 12.04.2011    source источник
comment
ознакомьтесь с этим ответом - stackoverflow.com/questions/1836175/   -  person yellowblood    schedule 12.04.2011


Ответы (7)


Я читал, что к защищенному члену можно получить доступ из производных классов. Почему мое использование слова «защищенный» не работает?

Это незаконно, потому что вы не предоставили гарантии, что получаете доступ к данным экземпляра «B». Рассмотрим аналогичный случай:

abstract class BankAccount
{
    protected int accountNumber;
}
class SwissBankAccount : BankAccount
{
}
--- in another assembly, evil-doers write ---
class EvilBankAccount : BankAccount
{
    void DoEvil()
    {
        BankAccount b = GetASwissBankAccount();
        int number = b.accountNumber;
    }
}

EvilBankAccount не наследуется от SwissBankAccount, поэтому защищенный член SwissBankAccount не может использоваться внутри EvilBankAccount. Вам разрешен доступ к защищенным членам ваших «родителей», но не вашим «братьям и сестрам»! EvilBankAccount может получить доступ только к защищенным членам EvilBankAccount (или типу, производному от EvilBankAccount). Доступ к защищенным членам SwissBankAccount запрещен.

Правило состоит в том, что тип выражения «получателя», к которому осуществляется доступ через, должен быть, по крайней мере, таким же производным, как и объявление типа, содержащее доступ к члену. Точную формулировку правила и некоторые наглядные примеры см. В разделе 3.5.3 спецификации C # 4.0.

Кстати, в C ++ тоже есть это правило.

Это правило часто понимают неправильно. Более подробный анализ этого правила и некоторых других последствий защищенного доступа можно найти в моих статьях на эту тему. Самые актуальные статьи, которые я написал на эту тему, - это этот и этот. Я написал еще несколько статей на похожие темы здесь (хотя некоторые из них уходят от темы самого защищенного доступа к теме того, как использовать защищенный доступ для построения модели данных с родительскими ссылками.)

person Eric Lippert    schedule 12.04.2011
comment
@FreeAsInBeer: Что ж, вы имеете право на свое экспертное мнение. Я не думаю, что ваш ответ действительно ответил на вопрос. Вместо того, чтобы отвечать, почему это использование protected не работает? как и я, вы вместо этого решили сказать, что делаете что-то неправильно, даже не объяснив, какое правило C # вызывает ошибку. Мне часто задают этот вопрос; это тонкий момент языкового дизайна и безопасности типов. - person Eric Lippert; 12.04.2011
comment
@FreeAsInBeer: вы знаете, кто такой Эрик Липперт, верно ?? - person marc_s; 12.04.2011
comment
@marc_s: Хотя я понимаю вашу точку зрения - и это очень забавно, что кто-то, кто учился в третьем классе, когда я впервые отвечал на подобные вопросы о дизайне языков программирования, пытается меня обучить - давайте вспомним, что StackOverflow - это основанная на сообществе система. Ответы оцениваются сообществом на основе их предполагаемой правильности и полезности, а не на основании предполагаемых полномочий человека, дающего ответ. Если молодой хозяин Бир считает, что я дал дерьмовый ответ, он определенно имеет право на свое мнение, и мы не должны ему отказывать в этом. - person Eric Lippert; 12.04.2011
comment
Поскольку еще никто не сделал этого, я поддержал этот ответ. Да, это немного сложнее, чем ожидал спрашивающий, но это потому, что она задала вопрос, который был немного сложнее, чем она поняла. Стоит пару раз перечитать, пока не поймешь. Иметь другие, более простые ответы тоже здорово. Вот почему несколько человек могут публиковать ответы. - person Cody Gray; 12.04.2011
comment
@Eric Lippert: конечно - отличное сообщество, которое ТАК тоже есть! Я просто предполагаю, что с вашей позицией (в качестве члена группы разработчиков C # в Microsoft) вы, вероятно, действительно имеете немного больше понимания того, как работают определенные вещи в C #, чем большинство < / b> другие программисты :-) - person marc_s; 12.04.2011
comment
@FreeAsInBeer: Мой искренний совет - сделать глубокий вдох и не быть настолько эмоционально вовлеченным. Это сайт сообщества, и все мы здесь, чтобы помогать и учиться друг у друга, помогая друг другу решать технические проблемы. Хорошо программировать сложно, языки сложны, а сарказм никому не помогает. - person Eric Lippert; 12.04.2011

Вы неправильно настроили свой код. Класс B не должен иметь экземпляра класса A. Вместо этого сам класс B наследует защищенные переменные от класса A.

Ваш код должен выглядеть примерно так:

class A
{
   protected int Test;
}
class B:A
{
   public B()
   {
       int someInt = this.Test;
   }
}
person FreeAsInBeer    schedule 12.04.2011
comment
+1 Просто чтобы добавить - вы можете получить доступ к защищенным членам базовых классов из экземпляра производного класса - см. Здесь msdn.microsoft.com/en-us/library/bcd5672a%28v=VS.71%29.aspx - person tom502; 12.04.2011
comment
Дело в том, что я ожидал, что мне будет разрешен доступ к защищенным членам экземпляров базового класса, поэтому я просто попытался создать экземпляр базового класса в производном классе. - person Miria; 12.04.2011
comment
@Miria: Нет, потому что вы просто создавали ссылку на класс A. Несмотря на то, что ссылка была в производном классе, доступ по-прежнему ограничен, как если бы это была частная переменная, потому что вы не обращались к переменной через сам производный класс (this.Test). - person FreeAsInBeer; 12.04.2011
comment
@FreeAsInBeer: Ну, я был сбит с толку, я думал, что могу получить доступ к фактическим защищенным полям экземпляра класса, который является базовым классом. Я думал, что это как общедоступное поле, но только для производных классов. Так что я был неправ - person Miria; 12.04.2011
comment
Позвольте мне сказать вам, почему я проголосовал против вашего ответа. Вы полностью изменили исходный код вопроса. В исходном коде был член типа A в типе B, вы изменили его, чтобы тип B унаследовал от типа A, просто чтобы вы могли получить доступ к защищенному члену. Почему вы предполагаете, что пользователь хочет изменить иерархию наследования и избавиться от своего члена instanceOfA? - person SolutionYogi; 12.04.2011
comment
@SolutionYogi - B также наследуется от A в коде OP. - person Greg; 12.04.2011
comment
@FreeAsInBeer: Серьезно, парень, сделай глубокий вдох. Вы очень взволнованы по поводу правды и справедливости, но никто из нас не окажется в Гааге (я надеюсь). Простой факт в том, что это не очень хороший ответ. Он даже не начинает отвечать на заданный вопрос; помните, что на вопрос «почему» следует отвечать «потому что»; вы дали соответствующий ответ на вопрос "Как мне ответить". Воспринимайте это как возможность обучения; в следующий раз внимательно прочтите вопрос и поймите, какой вопрос действительно задается. - person Eric Lippert; 12.04.2011
comment
@FreeAsInBeer - С другой стороны, ваш ответ все равно набрал 50 репутации. Помните, что в море много других вопросов. - person Greg; 12.04.2011
comment
@ Эрик, @ Грег: Спасибо. Я ценю конструктивную критику и надеюсь дать более четкие ответы, которые позволят лучше ответить на этот вопрос в будущем. - person FreeAsInBeer; 12.04.2011
comment
Грег, вот что я получаю, когда спешу набрать комментарий. Ты прав. Моя ошибка. Но я все еще считаю, что удаление члена instanceOfA - это БОЛЬШОЕ изменение кода. - person SolutionYogi; 12.04.2011

Вы можете получить доступ к Test int внутри самого B класса. Однако вы не можете получить доступ к свойствам экземпляра. A не знает, что это дочерний элемент B, поэтому не будет предоставлять доступ к его свойству.

class A
{
    protected int Test;
}
class B : A
{
    public B()
    {
       Test = 3; //possible
       base.Test = 3;  //explicitly calling base member, but not necessary in this case
    }
}
person David Neale    schedule 12.04.2011

Поскольку B уже наследуется от A, вам не нужен отдельный экземпляр A.

   public B()
   {
     this.Test = 1; //possible
   }
person Town    schedule 12.04.2011

Вы можете получить к нему доступ через тот же класс, но не как публичный член базового класса.

class A 
{ 
    protected int Test; 
} 

class B:A 
{ 
    void TestMethod()
    {
         this.Test = 3; // Possible
    }
}

Проверьте модификатор доступа protected в C #.

person Homam    schedule 12.04.2011

Подклассы могут получить доступ к своим собственным унаследованным членам, помеченным как protected.

class A
{
   protected int Test;
}

class B : A
{
   public B()
   {
     this.Test = 42; // Possible
   }
}
person Greg    schedule 12.04.2011

Вам не нужно создавать экземпляр A, если вы наследуете A.

class A
{
   protected int Test;
}
class B:A
{
   public B()
   {
     this.Test = 666;
   }
}
person John Hartsock    schedule 12.04.2011