Best OOP practice for grandchild class calling methods from its parent

I would like to know the best practice to structure classes in order to call parent methods when the class has a grandparent.

Let’s say I have this scenario:

public class Vehicle : MonoBehaviour { // parent

    public bool moves;
    public bool flies;
    public float maxSpeed;

    public virtual void Initialize () {
        moves = true;
    }
}

public class Airplane : Vehicle { // child
    public override void Initialize () {
        base.Initialize ();
        flies = true;
    }
}

public class Jet : Airplane { // grandchild
    public override void Initialize () {
        base.Initialize ();
        maxSpeed = 400f;
    }
}

Now, if I create a GameObject with the Jet script attached, it will run the Vehicle initialization, but not the Airplane parent code (meaning it will not fly).

There are a few workarounds for this. One is moving the Airplane code to every child class, but then it defeats the purpose of using OOP. What would be the best practice to solve this problem?

Note: I cannot use constructors, because as far as I know, MonoBehaviour does not allow (or does not work well with) them. That is why I’m using a custom Initialize function to be called whenever the GameObject carrying this script is instantiated. Also, the code above does not use field initializers, because the real code does a lot more than set variables.

You may want to use interfaces for this.

Have a look at this free video, it’s part of my training course available here on Udemy.