These elements look to me as though they serve much the same purpose as pure virtual functions.
So what is that you can do with an interface, apart from multiple inheritance, that you can’t do with pure virtual functions?
It more or less is the same as pure virtual. With the big point being that a class can implement as many interfaces as you want but can only inherit from one class.
It is good if you need lots of objects to have a common method, but where how they method needs to be implemented varies.
Think of if a object needs to take damage, you could have a IDamageable interface that make objects implemeant TakeDamage(int value). But if say only a few objects need to be useable you can also have them implement IUseable.
So use works just like a class with a pure virtual or what c# calls a abstract method, but the ability to implement multiple interfaces is very powerful.
OK, imagine I have creating a game which consists of stationary elements like walls and moving elements like characters. Both can take damage but only the characters can move.
If I implemented these using traditional class inheritance and virtual functions it might look something like this:
class GameElement: Monobehavior
{
private int m_nDamage = 0;
public virtual void DoDamage(int nDamageAmount)
{
m_nDamage += nDamageAmount;
}
}
class GameCharacter : GameElement
{
private int m_nPosition = 0;
public virtual DoMove(int nMoveAmount)
{
m_nPosition += nMoveAmount;
}
}
class Wall : GameElement
{
private int m_nHeight = 0, m_nLength = 0;
public virtual SetDimensions(int nHeight, int nLength)
{
m_nHeight = nHeight;
m_nLength = nLength;
}
}
If I implemented with interfaces it might look something like this:
interface IDamge
{
public void DoDamage(int nDamageAmount);
}
interface IMove
{
public DoMove(int nMoveAmount);
}
interface IDimensions
{
public SetDimensions(int nHeight, int nLength);
}
class GameCharacter : Monobehavior, IDamage, IMove
{
private int m_nPosition = 0, m_nDamage = 0
public virtual DoMove(int nMoveAmount)
{
m_nPosition += nMoveAmount;
}
public void DoDamage(int nDamageAmount)
{
m_nDamage += nDamageAmount;
}
}
class Wall : Monobehavior, IDamage
{
private int m_nHeight = 0, m_nLength = 0, m_nDamage = 0;
public virtual SetDimensions(int nHeight, int nLength)
{
m_nHeight = nHeight;
m_nLength = nLength;
}
public void DoDamage(int nDamageAmount)
{
m_nDamage += nDamageAmount;
}
}
Now apart from arguments along the lines of “this is the way it is done these days”, what coding scenario would compel me want to chose the interface method?
Its a other tool in the toolbox, and it is not a use either or type thing. interfaces accel where you need several object types to expose the same method but the details about how the method is implemented differs object to object.
I also find for some cases inheritance trees can get a little ugly, when you starting having a need for objects that blur the lines between what you already have in your tree. Where with a interface say you want a wall that exposes the Use method you can just give it the IUseable interface and not worry about the calling code, or about having to shoehorn in the new method into your inheritance tree.
Also keep in mind you can make base classes in a inheritance tree use interfaces as well and the stuff that extend the class will already have the interface implemented.
Abstract methods must be overridden in all child classes. (Also the base class must be abstract.) Virtual methods can be overriden in any child class, but is not required to. An interface is very much the same as an abstract method. The big difference is how their implemented and called.
Say you have some cars in your game. You need to control every car using a single input script, while each car has its own script. You can easily do this by creating a class called Car, which has some virtual methods: Drive(some params), Turn(…) and so on. Each of these methods can be done in different way, while still being interacted with in the same way. For example you can have an automatic car which simply does not override the ChangeGear(…) method, and thus its empty and does nothing, and instead does something different in its Drive(…) method, compared to a manual car which has a Drive(…) method which is somewhat dependant on the use of ChangeGear(…) method.
Obviously you could use a set of interfaces for this, so why would I use inheritance? Mostly because it is easier to read and write in this case. You could have a Car currentCar variable and call it like currentCar.ChangeGear(…) instead of MonoBehaviour currentCar called like if(currentCar is IGearable) (currentCar as IGearable).ChangeGear(…)
So when is it easier to use an interface? Maybe you want a damage system in your game. And you want alot of things to be damagable. Obviously it would be pretty limiting to derive all your classes from a class called Damageable etc. since you may only derive from a single class which derives from a single class and so on. Adding a TakeDamage(…) to your Car script would not do much, since you want alot of stuff which isn’t cars to be damagable. Now I would make an interface called IDamageable, which required a TakeDamage(…) method and maybe a health variable. Then implement this IDamageable to all my car scripts (or make seperate script for dealing with car health so I wouldnt have to add to every single car script), and all my other damagable objects.
Essentially I would recommend using what takes the least amount of effort to write! Other than that, interfaces and abstract methods are pretty much the same thing, while virtual methods are also pretty much the exact same except you are not required to override it.
[QUOTE=“passerbycmc, post: 2654376, member: 771019”
Also keep in mind you can make base classes in a inheritance tree use interfaces as well and the stuff that extend the class will already have the interface implemented.[/QUOTE]
Mmmmm! That had not occurred to me for some reason.
OK perhaps I am beginning to see an advantage to interfaces. Let me see…
class GameElement
{
}
class MoveableGameElement : GameElement
{
}
class Character : MoveableGameElement
{
}
class StationaryGameElement: GameElement
{
}
class Wall: StationaryGameElement
{
}
As opposed to…
class GameElement
{
}
class Wall: GameElement, IDimensions, IDamage
{
}
class Character : GameElement, IDamage, IMove
{
}
So this could keep you code simpler and reduce the amount of overall typing you have to do. And I can also easily see how this interface thing would be an advantage if your were getting freelancers to implement chunks of your app for example.
But for simple apps with one or two people working on it, and that function much the same as s standard Windows application such as Bingo, its probably 6 of 1 or half a dozen of the other with respect to which method you should use.
the point is to know how things like this work and choose where and when you use them.
A good example is all of my base classes for characters and objects generally have a lot of interfaces on them, and the reason is if i do something like a raycast all i have to do is do a simple GetComponent for IDamageable to know if it can be damaged, since it would return null if nothing implements IDamageable. You can do the same for a object you already have reference for, if you cast using the “as” keyword since that will return null if it cant cast.
So as far as logic flow goes you can often use them as a way to define what kinda action words / verbs you can apply to a object. Which is also why you might notice most people use some sort of adjective to name a interface as if your asking can this be damaged, can this be used etc.
Ah well I will have to dip my toes in the water of interfaces and take it slow and easy.
Up until now I have relied entirely on inheritance and virtual functions - the Microsoft MFC way of coding.
I think I am beginning to see how this system could be a useful alternative to SendMessage(“FuncName”,…) and GetComponent()…either with out without my current Microsoft MFC like messaging system (base on unique integers).
Especially if the interface was inherited in to the lower most base class.
Just think of a interface like a cpp abstract base class that only contains pure virtual methods.
Interfaces force a class to share API, without forcing sharing of implementation. They provide a variety of advantages. Here are some thoughts.
Intefraces promote modularity. By putting an interface between classes, you can swap out either end with ease.
Interfaces reduce dependency. In general a class should be only dependent on the API it actually uses. An interface can be used to limit dependency.
You can implement as many interfaces as you like.
Interfaces make it trivial to produce stub classes for unit testing and development and the like.
While you are considering inheritance and interfaces, you should also consider composition. Composition is at the heart of Unity’s design pattern. And is arguably more important and useful within Unity then inheritance or interfaces.
I just wrote a post explaining Interfaces if you are looking for more info.
Its worth noting that if you keep all of your class to class communication through the messenger system you showed in that other thread, then interfaces won’t buy you much at all. Inheritance will do the job just fine.
Interfaces are really ways to help govern and control class to class communication.
Surely you would still need to come up with some system for standardizing such interfaces?
Otherwise you may end up effectively creating spaghetti code through dozens and dozens of interface functions.
That is the purpose of Windows API WindProc function that all windows applications must possess as a standard message ‘entry point’ for your assorted windows objects.
MFC is just a OO wrapper for the underlying windows API and their macro based message map system is a wrapper for the WindProc function.
But it does make it quite easy to debug - you always know exactly where to go to figure out where to put your break points no matter the class or who wrote it.
How do people generally replicate this sort of standardisation in Unity interfaces?
Also I tried the following again:
public void SendMessage(GameObject gameobj, Parameters parameters)
{
if (gameobj != null)
{
parameters.m_gameobjSender = gameObject;
//gameobj.SendMessage("DoDispatchMessage", parameters);
McCormickMonoBehaviourBase script = gameobj.GetComponent<McCormickMonoBehaviourBase>();
script.DoDispatchMessage(parameters);
}
else
{
string strError = "McCormickMonoBehaviourBase.SendMessage(GameObject gameobj, int nMsgID, Parameters parameters) - gameobj is null...";
Debug.Log(strError);
}
}
And it worked just fine - I stepped through the override functions in my derived classes.
So I don’t know how I @ucked it up the first time I tried it
So I don’t need to use SendMessage(“func name”) any more.
I also implemented an associative array thing (gameObject.name vs gameObject) so that I could implement my own FindGO(“game object name”) function. So I no longer need to rely on GameObject.Find(…).