简体   繁体   中英

Why use a constructor over protected variables?

I'm building some classes within unity to define the mechanics individually, and transition between each for easier and cleaner code.

What I wanna know, is when should I be using a constructor to pass variables around, and when to use protected variables. What are the pros and cons of each, and what should I know about them? Also what should I lean towards, like what's practical?

Previously I'd pass these variables into the PlayerState constructor, then in my classes that extend from my PlayerState would follow suit. But if they're protected variables I don't need to pass them into the constructor to access them, and I was wondering what should I do? using UnityEngine;

The new way I'm doing it:

public class PlayerState
{
    //protected Core Core;
    protected Player player;
    protected PlayerStateMachine StateMachine;
    protected PlayerData playerData;
    private string currentAnimation;
    protected float StartTime; // Start time gets set everytime we're in a state, that way we have a reference for how long we've been in any state (good for mechanics)
    protected bool isAnimationFinished;
    protected bool isExitingState; // Very useful, if you run through if/else conditionals in a superState, the substate may still run, and both end up calling a change state. This will stop this from happening

    public PlayerState(string currentAnimation)
    {
        this.currentAnimation = currentAnimation;
    }

    public virtual void Enter() { }
    public virtual void Exit() { }
    public virtual void LogicUpdate() { }
    public virtual void PhysicsUpdate() { }
    public virtual void DoChecks() { }
}

The Old Way:

public class PlayerState
{
    protected Core Core;
    protected Player player; // protected means private but shared between components that inherit the class
    protected PlayerStateMachine StateMachine;
    protected PlayerData playerData;
    private string currentAnimation;
    protected float StartTime; // Start time gets set everytime we're in a state, that way we have a reference for how long we've been in any state (good for mechanics)
    protected bool isAnimationFinished;
    protected bool isExitingState; // Very useful, if you run through if/else conditionals in a superState, the substate may still run, and both end up calling a change state. This will stop this from happening

    public PlayerState(Player player, PlayerStateMachine stateMachine, PlayerData playerData, string currentAnimation)
    {
        this.player = player;
        this.StateMachine = stateMachine;
        this.playerData = playerData;
        this.currentAnimation = currentAnimation;
        Core = player.Core;
    }


        // So now we code out the functions for each state
    // Every state must have an enter and exit function, as well as an update and fixedUpdate function
    // We're naming the update function as "LogicUpdate", and fixedUpate as "PhysicsUpdate"

    public virtual void Enter() // virtual means this function may be overriden from classes that inherit this class
    {
        DoChecks();
        player.Anim.SetBool(currentAnimation, true);
        StartTime = Time.time;
        isAnimationFinished = false;
        isExitingState = false;
        //Debug.Log("Current Animation: " + currentAnimation);
    }


    public virtual void Exit()
    {
        player.Anim.SetBool(currentAnimation, false);
        isExitingState = true;
    }

The way I applied it to other classes the old way:

public class PlayerGroundedState : PlayerState
{
    protected Vector2 input;
    protected bool jumpInput;
    private bool grabInput;
    private bool dashInput;
    private bool isTouchingGround;
    private bool isTouchingWall;
    protected bool willCollideWithCeiling; 

    public PlayerGroundedState(Player player, PlayerStateMachine stateMachine, PlayerData playerData, string currentAnimation) : base(player, stateMachine, playerData, currentAnimation)
    {
    }


    public override void Enter()
    {
        base.Enter();
        player.JumpState.ResetAmountOfJumpsLeft();
        player.DashState.ResetCanDash();
    }


    public override void Exit()
    {
        base.Exit();
    }

I don't have to pass player into the constructor of PlayerState and PlayerGroundedState to access it if it's protected. What should I do though, which method is the proper way to handle the variables, also which is better for my cpu?

This is just a question related to OOP. Unity is not needed to be considered.

A constructor let you create an object instance and initialize the members of the object at the same time. If there are some immutable members (ie they will never be changed after construction), you may need to initialize them in constructors, and you may add the keyword readonly to the members. If you don't need to initialize any member with passing parameter(s) when the instance is created, there is no need to have a custom constructor (unless you want to hide the default constructor).

The access modifier protected makes the member accessible only in code in the same class, or in a class that is derived from that class. If you need to access the member in other places, you still need do it via public/internal methods such as setters and getters, or make it public / internal .

In your case, I think a constructor is needed to initialize the members such as player when a PlayerState instance is created.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM