abstract functions/classes force the inheritor to assign a value.
Is it possible to make a variable abstract to force the compiler to throw an error if the variable is unassigned by the inheritor?
basically
if i have
WeaponBaseClass
{
float accuracy;
float damage;
float recoil;
}
can i do something in the declaration so if i do
MachineGun : GunBaseClass
{
//forget to assign a value to damage/recoil/accuracy etc;
}
if i forget to actually give the variable a value it throws an error.
I do not want to place the variable in the MG class because all weapons will have this and i want the commonality of the variable being in the base class.
I dont want a default value. If I forget to assign something I want an error, not a default value because the default value will result it in producing very close to what I want. That is it’ll have some damage, some accuracy, but not perhaps the intended value which means I may not even notice its “broken”.
You can’t have abstract fields, but you may be able to do something with properties:
public abstract float accuracy{get;set;}
Note: Properties aren’t by themselves serializable in an inspector, but there are ways around that if you’re savvy.
Hope that helps.
==
Boolean flags and nullable types overcomplicate this requirement a little in my opinion. Instead, I suggest making a protected constructor in the abstract class and have it take the variable you want to make sure your subclasses set. The deriving classes then call the parent constructor next to their own, passing the required variable. That’s the classical object oriented way to do this. And for the record - you’re right to keep the common variable in the base class. That’s what base classes are for.
Please see this Stack Overflow post for the solution I’m talking about:
It also contains a relevant code sample.
My preferred method:
You should create an initialization function for each subclass, and have a boolean flag in the abstract which is set to true only after the initialization function is run. This means that you’ll have to check the boolean every time you want to do anything with it, and throw an error if it’s false. Also, if you use my script, you can not have an Awake in any subclasses, as they will take priority and Awake in the base class will never be called automatically.
public abstract class WeaponBaseClass : MonoBehaviour {
protected float accuracy;
protected float damage;
protected float recoil;
protected bool isInitialized = false;
void Awake() {
Init();
}
abstract protected void Init();
}
public class MachineGun : WeaponBaseClass {
protected override void Init ()
{
//set values here
isInitialized = true;
}
}
An Alternative method:
Use nullable objects. They will thrown an error if they’re not assigned, but used in e.g. arithmetic operations. You will also have to explicitly cast them to floats, but that can be done in a public property as per as the earlier answer.
public abstract class WeaponBaseClass : MonoBehaviour {
protected float? accuracy = null;
protected float? damage = null;
protected float? recoil = null;
}
public class MachineGun : WeaponBaseClass {
void Start(){
//forgetting this will cause an error
accuracy = 3f;
}
public void Update(){
float test = 2;
test += (float)accuracy;
Debug.Log(test.ToString());
}
}