Question about protected and abstract classes.
I'm about 2 weeks into C# now, and I have a quick question about abstract classes and protected functions;
Are abstract classes just a script of functions/variables to be shared between scripts? Essentially making them a companion script for other scripts to reference? No value on their own?
What exactly is protected? Is it just so other scripts don't overwrite a function with their own function?
Ex: Class A Start() doesn't overwrite Abstract Class B Start() when being referenced?
This is a basic question, but want to be sure if I ever need to use abstract classes, I'm using them correctly.
Abstract is often explained alongside Virtual, as both of these deal with implementing something at the inheritance level. This question had a nice answer:
edit for immediate clarity:
Virtual: You are setting up an original version of a function, but the derived class may / can to overwrite this original one if it chooses to.
Abstract: You cannot set up an original version. You are requiring that anything descending from that class must make its own version.
Protected: Only derived / inherited classes can use that value; the original class cannot. The msdn example was succinct:
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/protected
Answer by Bunny83 · Jun 23, 2017 at 03:03 AM
In general a virtual or abstract method is a method that can be overridden in a child class. The only difference between a virtual and an abstract method is that an abstract method doesn't have an implementation yet. So it's similar to an interface definition. An abstract method is basically a "contract" that any non-abstract class instance that is derived from that base class will have a method with that signature (name, parameters, return type).
Note that if a class contains any abstract members, the class itself has to be abstract as well. If a class is abstract you can not create an instance of that class since it might have "abstract members". So it might define methods which don't exist in the base class. Non-abstract derived classes have to implement all abstract members of it's base class(es).
An abstract base class is usually used when the base class on it's own has no actual function besides providing a common interface / common functionality for it's child classes. The typical example of an "Animal" base class would be a prime example for an abstract class. It makes no sense to create an instance of the Animal class. Only derived classes (like Dog, Cow, Cat ...) may be instantiated.
The "protected" keyword is called an "access modifier". Every member of a class (fields, properties, methods) always have an "access level". The most general ones are public and private. Public methods are methods that can be accessed from outside the class. They form the "interface" of the class. private methods on the other hand can only be accessed within the class. So private methods are "invisible" from outside the class. They also can't be accessed from a derived class. Protected members are like private members. They can't be accessed from outside the class, so they don't belong to the interface of the class. However they can be accessed by derived child classes. That's the only difference.
A quick example to show the usage of public, protected and private as well as virtual and abstract.:
public abstract class BaseWeapon
{
public int ammo;
public void FireWeapon()
{
if (CanFireWeapon())
{
InternalLaunchProjectile();
ammo--;
}
}
public virtual bool CanFireWeapon()
{
return EnoughAmmo();
}
public abstract void Reload();
protected abstract void InternalLaunchProjectile();
private bool EnoughAmmo()
{
return ammo > 0;
}
}
public class Gun : BaseWeapon
{
public float fireRate = 10;
public int clipCount = 4;
public int clipSize = 20;
private float coolDownTime;
public override bool CanFireWeapon()
{
if ( !base.CanFireWeapon() )
return false;
if ( Time.time < coolDownTime)
return false;
return true;
}
public override void Reload()
{
if (clipCount > 0 && ammo < clipSize)
{
ammo = clipSize;
clipCount--;
}
}
protected override void InternalLaunchProjectile()
{
if (Raycast( ... ))
{
coolDownTime = Time.time + 1f / fireRate;
// apply damage to the object we hit
}
}
}
public class RocketLauncher : BaseWeapon
{
public float reloadDelay = 5;
private float coolDownTime;
private bool loaded = false;
public override bool CanFireWeapon()
{
if ( !base.CanFireWeapon() )
return false;
if ( !loaded || Time.time < coolDownTime )
return false;
return true;
}
public override void Reload()
{
if (!loaded)
{
loaded = true;
coolDownTime = Time.time + reloadDelay;
}
}
protected override void InternalLaunchProjectile()
{
// instantiate rocket prefab here
loaded = false;
}
}
Now inside your player class you may have a variable like this:
public BaseWeapon currentWeapon;
This could reference either a Gun instance or a RocketLauncher instance. Though the player script doesn't need to know which weapon is active as it just needs to call "FireWeapon" to fire the weapon and "Reload()" if the user wants to reload.
void Update()
{
if (currentWeapon != null)
{
if (Input.GetButtom("Fire1"))
currentWeapon.FireWeapon();
if (Input.GetButtonDown("Reload"))
currentWeapon.Reload();
}
}
ps: the code is not tested but the concept should be clear.