- Home /
Subclassing in C#?
I know this is more of a C# question than a Unity question, but I figure it's relevant all the same, and may help others as well in their endeavors. I have a couple questions all related to subclassing. (Whoa, first time I've typed in a title and UnityAnswers didn't have a single related suggestion for me!)
How do I do it? I've actually done a lot of searching about this on Google but I haven't found any simple, easily-understandable answer. MSDN articles are way too complex when it comes to explaining things like this.
Am I correct in assuming that subclassing would be useful for, say, having one script called "Health" and having every separate AI script subclass from it, thus allowing me to more or less "blindly" apply health changes to any enemy regardless of his type?
If I subclass in Unity, can I just apply the last script in the hierarchy to my game object? I assume I would need to apply all the scripts manually, but I'm just making sure.
Thanks.
Answer by Statement · Apr 16, 2011 at 07:40 PM
You subclass each time you write a C# script in Unity.
public class MyScript : MonoBehaviour // Subclassing MonoBehaviour
{
}
Yes, you could make a subclass called Health, although it's not very "component-based".
public class Health : MonoBehaviour { public int health; }
public class Enemy : Health { // will inherit "health" }
public class Player : Health { // will inherit "health" }
You don't often say "Enemy is a Health" but rather that "Enemy has Health", and it's a good rule of thumb for deciding when to use subclassing or slap on another component on them. Although we could just change our perspective and think of all the properties a "Character" has. You can only inherit from one base class (that base class can in turn inherit from something else). This next approach isn't much better, but it's a better name at least.
public class Character : MonoBehaviour { public int health; // has health // Whatever else you can think of. }
public class Enemy : Character // Enemy is a Character { // will inherit "health", Enemy has health }
public class Player : Character { // will inherit "health", Player has health }
"Enemy is a Character", and "Characters have health".
So yeah, you can just replace the : MonoBehaviour for : MyOtherBaseClass, as long that base class evenutually inherit from MonoBehaviour. This applies when you want your classes to have the property of being placed on game objects.
A tip: For many things you want to share/mix properties of several concepts. Perhaps you want to have a Health script that your Enemy and Player want to use. You could add a health script to the same game object that has the enemy or player script. This is about separation of concerns, and your player/enemy would access the health script rather than have it built in, however how you prefer to write your code is entirely up to you. If you prefer to have health and other properties baked into a base class, go for it.
So, just to give you a little bit of options for your subclassing endevour, you should know about overriding methods.
public class Character : MonoBehaviour { public void Speak() { print("I spoke!"); } }
public class Player : Character { // Can also Speak }
It would be nifty if Player could change how it speaks. We can change this with virtual methods. We change our Speak in Character to be virtual, and override Speak in Player.
public class Character : MonoBehaviour { public virtual void Speak() // Added the 'virtual' keyword { print("I spoke!"); } }
public class Player : Character { public override void Speak() // Added the 'override' keyword { print("Player spoke!"); } }
In this setup, if you had a reference to a Character type, that actually held a Player object, and called Speak(), it would execute Players version of Speak instead of the Characters version. It's a very silly method I wrote here, but the idea is that you can choose to do other things differently. Like, "UpdateMovement" might be done differently for an AI player than a Human Player. The human player would accept Input to make movement, and the AI player might make use of an A* Algorithm to traverse the level.
I hope it helped somewhat.
A short summary:
- Subclassing give you all the properties and methods (all members) of the base class.
- You can change the behaviour of methods by using the virtual and override keywords.
- You can substitute any sort of Character where there's a Character reference needed.
- Base classes are chosen with the : operator after the class name.
- Unity scripts must subclass MonoBehaviour at some point in their inheritance.
- Try to think of names for subclasses in a "is a" manner. What sounds correct?
- "Player is a Health"
- "Player is a Character"
- "Player has a Health"
- "Player has a Character"
- The "is a" suggest to favor inheritance over compostion.
- The "has a" suggest to favor composition over inheritance.
- Done with member variables or another shared component on the same G.O.
Any beginner book in C# will go through all the options in the topic of subclassing or implementing interfaces. I highly suggest you buy/borrow/s$$anonymous$$l one if you want to fill in this gap of knowledge. (Well, s$$anonymous$$ling is bad karma, so borrow rather than s$$anonymous$$l, mkay?)
Oh, right. I didn't want to give off the wrong idea. I couldn't think of a good way to word it originally, but I do understand that when you subclass, it's better practice to say that, for instance, Box is an Object, and perhaps all Objects have Health. Thanks for the explanation though, was much more helpful than what I got out of any of the $$anonymous$$SDN articles I've read. It hadn't occurred to me that we're already subclassing with $$anonymous$$onodevelop, didn't know what the significance was of the colon. :) Player is a Character, Character has Health, etc., and Player : Character. Think I've got it.
I also noticed you include all the classes in one script. Seems like the best way to do it for one subclass, but when you get multiple subclasses, shouldn't I have, for instance, Character as one separate script in Unity, and then each subclass of Character as another separate script? Seems like if I did Character, Player, and Enemy all in the same script and added that to a GameObject, then that GameObject would end up being both a Player and an Enemy...
No, I just dont have a lot of time to format each "snippet" but they should be in separate files. Generally you put each class in a file of their own. I suggest you do the same.
Got it. Thanks for all your help, marked as answered as everything is clear to me now.
Your answer
Follow this Question
Related Questions
Using GetComponent with a subclass 3 Answers
Does Unity support Inheritance and Subclassing? 9 Answers
Does Unity support multiple Inheritance? 3 Answers
Trying to call a variable from another script in C# 1 Answer
Is Instance Of 3 Answers