- Home /
How to call child overide function?
Hi all,
I'm trying to grasp Virtual / Override functions. And it seems I fail.
All interractable objects (door, chest, ...) will have a script "ObjectAction" attached to them containing a virtual "Use" function. They will also have a script (Door.cs, Chest.cs, ...) for their own use of this "Use" function (door will play an opening door animation, chest would open and open its inventory,...) .
But how do I call the child funtion? What I currently do is:
gameObject.getComponent<ObjectAction>().Use();
but this obviously does not work and calls indeed ObjectAction.Use(). But I would expect that Door.Use() or Chest.Use would of been called as they are supposed to override it.
It sounds to me that I miss something that should be simple, but did not find my way to make it work.
if needed, here are both my test scripts attached on the 'Door' prefab/gameObject:
pubic class ObjectAction : MonoBehaviour
{
public virtual void Use()
{
print ("Object Action use");
}
}
public class Door : ObjectAction
{
public override void Use ()
{
print ("Child door Use");
}
}
Should I call manually Door.Use()? If so, what is the benefit of override? I count of having a large amount of little scripts overriding 'Use' and thought virtual/override functionallity would allow me to simply call ObjectAction.Use without needing to know what specific object I was interracting with.
Thank you for reading/helping
Answer by UsmanAbbasi · Dec 30, 2015 at 10:19 AM
Do not attach "ObjectAction" script on game objects. Just attach the the child class (door,chest,etc whatever it is). When you attach both scripts and call this gameObject.GetComponent<ObjectAction>().Use();
then you get ObjectAction component which does not know about child classes but when you attach only the child class(door,chest,etc) then gameObject.GetComponent<ObjectAction>().Use();
will get "ObjectAction" object through the child class and then it knows about the child class and will call the overridden method.
Thank you Usman, but my question remains then: How do I then call the "Use" function? without calling Door.Use or Chest.Use
I've edited the answer to fix the missing syntaxhighlighting. $$anonymous$$aybe the answer makes more sense now ^^.
When you derive a class from a base class, that class "is" also the base class. The most common example is usually an "Animal" base class and some concrete child classes like Cow, Cat, Dog. When you create an instance of "Cat", that instance is also an Animal. That's why you could do:
Animal a = GetComponent<Cat>();
Here you have a reference "a" of type Animal but you stored the reference to a Cat. This is called "upcasting" where you treat a child class like it's just a base class. "a" actually references a Cat but the compiler only allows you to access things that are defined in "Animal". The compiler doesn't know if "a" will contain a Cat, a Dog or a Cow, it's just an Animal.
The reverse process is also possible, but requires an explicit cast. This is called downcasting. While an upcast to a base class will always work (as long as it actually is a base class of the class) a down cast can fail. Example:
Animal a = GetComponent<Animal>();
Dog d = (Dog)a; // downcast
Here we get any Animal component that is attached to this gameObject. So a contains a reference to either an Animal, a Dog, a Cat or any other derived type. In the second line we perform a downcast to the more concrete type "Dog". This cast will fail and throw a casting exception if the reference stored in "a" is not a Dog or a type derived from Dog.
upcasting is the process of generalising / abstracting the access to objects by treating them equally as their base class. Once abstracted you actually loose access to specific things of the child classes. You can only access things defined in the base class.
downcasting is the reverse process. When you have an abstracted reference to an object and you need access to specific members of a child class.
upcasting helps to decouple dependencies between several classes since they don't have to know each other. It's enough when they know their base class or interface.
Just another example to make clear how your object inheritance chain actually looks like:
Door -> ObjectAction -> $$anonymous$$onoBehaviour -> Behaviour -> Component -> UnityEngine.Object -> System.Object
So an instance of the Door class is also an ObjectAction as well as a $$anonymous$$onoBehaviour, a Component and an object. Each base class added more functionality. For example you can treat a Door as a Component:
Component c = GetComponent<Door>();
However you can only use things that are defined in the Component class. For example:
GameObject g = c.gameObject;
"c" could contain any component. In this case we don't need to know that the component we talk about is a Door. Every component has a gameObject property to access the gameobject it's attached to.
Likewise we could upcast to UnityEngine.Object:
UnityEngine.Object o = GetComponent<Door>();
In this case we can only use the door as an Object. You can't do much with such an object except Destroying:
Destroy(o);
The ultimative upcast would be
object o = GetComponent<Door>();
The "object" class (alias of System.Object) is the base class of everything in .NET. All class instances can be upcasted to this type. However it provides almost no funtionality.
Thank you both. I know understand what you meant as of course is working like a charm. Thank you Bunny for your detailed explanations.
I think something that bugged me a lot is that my inherited class causes issues in $$anonymous$$onoDevelop. $$anonymous$$y 'Door' inherits from 'ObjectAction' wich in turns inherit from $$anonymous$$onoBehaviour. But while in 'Door', autocompletion/IntelliSense does not seem to work like expected. Simple 'GetComponent' or 'Print' seem not allowed in $$anonymous$$onoDevelop, though are correctly compiled and ran by Unity.
I know this is not the initial question, but is this normal? Is it possible to use autocompletion/IntelliSense on inherited class?
Thank you @Bunny83 for fixing the missing syntax highlighting. This is the line you will use to call the function without without calling Door.Use or Chest.Use
gameObject.GetComponent<ObjectAction>().Use();
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Function GUI with a Return value 1 Answer
A NullReferenceException even though I'm sure that object was assigned? 1 Answer