Можете ли вы изменить приватное поле суперкласса? - PullRequest
1 голос
/ 20 декабря 2011

Я работаю с базовым классом с закрытым исходным кодом . Могу ли я как-то изменить приватное поле в базовом классе из моего унаследованного класса?

Предполагая следующую структуру класса:

public class Parent
{
    private bool age;
}

public class Baby : Parent  
{
    public bool newAge{
        get {
           return age;
        }
    }
}

В настоящее время выдается ошибка компиляции:

 'Parent.age' is inaccessible due to its protection level.

Как вы получаете доступ к полю "возраст" из класса Baby? Можете ли вы использовать отражение или что-то подобное?

Ответы [ 5 ]

5 голосов
/ 20 декабря 2011

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

public class Baby : Parent
{
    private readonly FieldInfo _ageField = typeof(Parent).GetField("age", BindingFlags.NonPublic | BindingFlags.Instance);
    public int newAge
    {
        get
        {
            return (int)_ageField.GetValue(this);
        }
        set
        {
            _ageField.SetValue(this, value);
        }
    }
} 

Если это предоставлено третьей стороной, ничто не мешает им изменить его, переименовать, удалить все вместе. Это одна из точек private. Имейте в виду, что это может быть частным по причине. Повозиться там, где вы не должны, может привести к неожиданным результатам.

4 голосов
/ 20 декабря 2011

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

typeof(Parent)
.GetField("age", BindingFlags.Instance | BindingFlags.NonPublic)
.SetValue(parent, 14);

, где parent - это экземпляр Parent.

.
2 голосов
/ 20 декабря 2011

Вы можете изменить эти значения с помощью отражения. Это, как говорится, вы, вероятно, не должны.

Закрытые поля, свойства и методы - это все, что явно не гарантируется договором класса. Если этот сторонний API надежен, публичные контракты, которые они предоставляют, не изменятся (но они могут легко расти ).

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

Если вы пойдете по этому пути, я бы порекомендовал класс Adapter, который будет использовать весь ваш код, использующий ваш код, вместо этого стороннего API. С шаблоном Adapter, только один класс должен будет измениться в ответ на изменения API 3-ей части.

2 голосов
/ 20 декабря 2011

Ну, поскольку вы не можете изменить исходный код родительского класса, возможно, есть 2 варианта:

  1. Если родительский класс является частичным классом, вы можете определить свой собственный вклад (другой родительский класс), определяющий публичное свойство (оно может получить доступ к закрытым полям).

  2. Вы действительно можете использовать отражение.

1 голос
/ 20 декабря 2011

Нет, вы не можете это сделать.Если вы не используете отражение, например:

Reflection.FieldInfo fields[] = 
    myType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...