← Назад к вопросам

Кому доступны переменные protected

1.2 Junior🔥 121 комментариев
#C# и ООП

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Доступ к переменным с модификатором protected в Unity/C#

Модификатор доступа protected определяет специфичный уровень видимости переменных, методов или свойств внутри семейства классов, основанного на наследовании. В контексте Unity, которая использует C#, его поведение полностью соответствует стандартам языка.

Основное правило доступа

protected члены класса доступны:

  1. Внутри самого класса, где они объявлены (как и private члены).
  2. Внутри любого производного класса (наследника), независимо от того, находится ли наследник в том же или в другом пространстве имен (namespace) или сборке (assembly).

Ключевое ограничение: protected члены не доступны из любого другого кода вне семейства классов, включая другие классы, которые не являются наследниками, и код, работающий с экземпляром класса через переменную базового типа.

Практический пример в Unity

Рассмотрим классическую иерархию игровых объектов.

// Базовый класс в одном файле
public abstract class Enemy : MonoBehaviour
{
    protected int baseHealth = 100;
    protected float movementSpeed = 5f;

    protected void TakeDamage(int damage)
    {
        baseHealth -= damage;
        Debug.Log($"Enemy health: {baseHealth}");
    }

    public virtual void Attack() { }
}

// Производный класс в другом файле (или даже сборке)
public class OrcEnemy : Enemy
{
    private bool hasShield = true;

    public override void Attack()
    {
        Debug.Log("Orc attacks with axe!");
    }

    public void SpecialAbility()
    {
        // Доступ к protected членам родителя разрешен
        TakeDamage(10); // Можно вызвать protected метод
        movementSpeed *= 2; // Можно изменить protected поле
        Debug.Log($"Orc sped up to {movementSpeed}");
    }
}

// Другой, несвязанный класс
public class GameManager : MonoBehaviour
{
    void TestAccess()
    {
        OrcEnemy orc = new OrcEnemy();
        // orc.baseHealth = 50; // ОШИБКА КОМПИЛЯЦИИ: недоступно

        Enemy genericEnemy = orc;
        // genericEnemy.movementSpeed = 10; // ОШИБКА КОМПИЛЯЦИИ: недоступно

        // Правильный доступ только через публичный API наследника
        orc.Attack(); // Доступно, так как метод public
        orc.SpecialAbility(); // Доступно, так как метод public
    }
}

Важные сценарии использования protected в Unity

  • Создание расширяемых базовых классов: Когда вы создаете абстрактный класс Weapon, State или Ability, вы можете сделать ключевые внутренние поля (cooldown, isActive) protected, чтобы наследники (FireballAbility, SwordWeapon) могли напрямую управлять логикой, но внешние системы (Inventory) не могли вмешиваться.
  • Шаблон "Фабричный метод" (Factory Method): Базовый класс может объявить protected abstract метод для создания объекта, который наследники обязаны реализовать, но который скрыт от клиентского кода.
  • Контроль над жизненным циклом компонентов: В собственном MonoBehaviour вы можете сделать метод protected virtual void OnInitialize(), который вызывается в Start(). Наследники могут переопределять его, добавляя свою логику инициализации, но внешний код не может вызвать его напрямую, нарушая порядок.

Отличие от private и protected internal

  • private: Доступ только внутри класса-владельца. Наследник не видит private поля родителя.
  • protected internal: Доступен внутри всей сборки (assembly), где объявлен, и также всем наследникам, даже из других сборок. Это объединение двух модификаторов.

Рекомендации для Unity разработчика

  1. Используйте protected для членов, которые являются частью внутренней логики семейства классов, но не должны быть частью публичного контракта (API) для всего остального мира.
  2. Для данных, которые должны быть доступны наследникам, но также и другим системам внутри проекта (в одной сборке), рассмотрите protected internal.
  3. Часто protected virtual методы используются для предоставления "точек расширения" (extension points) наследникам, позволяя им изменять поведение без изменения базовой алгоритмической структуры.
  4. Помните, что в Unity, если protected поле объявлено в классе, производном от MonoBehaviour, оно не будет автоматически отображаться в Инспекторе (Inspector). Для этого требуется модификатор [SerializeField] или объявление как public.

Таким образом, protected — это инструмент для контролируемого раскрытия деталей реализации строго внутри вертикальной иерархии классов, что способствует созданию чистого, безопасного и расширяемого кода в Unity проектах.