Overriding methods with different params

Monkey Forums/Monkey Programming/Overriding methods with different params

Grey Alien(Posted 2013) [#1]
Yeah I've read the threads that say you can't do it and there's no override keyword, but what is the best method to do something similar then?

1) Add a dummy method with the same params to the base class (yuk)
2) Make a different method name for the one with different params (pretty bad if you want to iterate a list of various different classes and call the same method polymorphism-style)
3) Something obvious I'm missing?

Thanks!


Grey Alien(Posted 2013) [#2]
I also noticed that solution 1 breaks if you have say:
- Class A with two versions of same method
- Class B extends Class A and has only one of Class A's methods.
- Class C extends Class B and tries to override the method from Class A that is missing in Class B.

Basically you have to add the dummy function all the way up the class tree, which is super-bad it seems to me.


Belimoth(Posted 2013) [#3]
I think someone will say that trying to override a method with different parameters is a symptom of "Bad OOP design" but I'm sure you know what you're doing.
A third solution would be to have the function only take one parameter, a MyInfo object which is handled differently.


therevills(Posted 2013) [#4]
You can have the same method name with different params... as long as the signature is different.

[monkeycode]Strict

Function Main:Int()
Local s:Sprite = New Sprite
s.Draw(100, 100)
s.Draw(100, 120, True)
Return 0
End

Class Sprite
Field x#, y#

Method Draw:Void(x#, y#)
Print("Draw @ "+x+","+y)
End

Method Draw:Void(x#, y#, shadow?)
Draw(x, y)
If shadow
Print("Drawing Shadow...")
End
End
End[/monkeycode]
What are you trying to do?


wiebow(Posted 2013) [#5]
I try not to use this feature as it is confusing and can generate hard to find bugs... I would name the 2nd method in your example DrawWithShadow(x,y)


Grey Alien(Posted 2013) [#6]
@Belimoth: Ah yes your third idea is a good one, although it could make it quite clunky for simple methods

@therevills: I have an update method in a base class with no params, then for an extended class I wand an update method with a single parameter passed in so I can do something different. In the end I made UpdateNoSound() which sets a field called useSound:int and then calls the normal Update() method.

@wiebow: Yeah I ended up doing that type of thing.


therevills(Posted 2013) [#7]
Sounds like you are more in need of using an Interface and adding the stub methods with the different parameters there.


Grey Alien(Posted 2013) [#8]
Well that's my method 1 suggest above right? I didn't fancy that.


muddy_shoes(Posted 2013) [#9]
As Belimoth suggested, this sort of thing does generally point to a OO design that's going off the rails a bit. However, taking it at face value:

There's something a bit contradictory about your first and second points in the top post. If it's ugly/wrong to have your second method in Class A then how would you ever have the situation in point 2 where you iterate over a list without care about the specific type? If A doesn't have the method then you'd need to test the type in order to work out what to call.

The issue you point out in your second post where Monkey "breaks" when you try to override a method in C that isn't explicitly defined in B, but is in A -- that's a Monkey bug (or, if claimed "as intended", it's a design flaw).

Another option in your situation would be to change the method in A to take a useSound flag with a default value of True. That way you can just call Update() as normal if you want. This would also likely allow you to separate the sound playing stuff into another method and only call that if the flag is true.


Grey Alien(Posted 2013) [#10]
Ah yes good point, my case 2 is totally invalid haha, oops.

Yeah I thought about adding a useSound param with a default to the method but it doesn't sit well with me that the base class doesn't have any sound and doesn't ever use that param. It just seems weird to me, and would be confusing for anyone reading the code.


muddy_shoes(Posted 2013) [#11]
That sort of takes us back to "off the rails" of OO for me. If A is a concept that cannot (rather than just does not) play sound in the update then B should also have that property because it is an A too.

Code aesthetics are an individual taste matter to some extent but pushing against the specialisation going down the inheritance tree flow is normally going to cause pain.


therevills(Posted 2013) [#12]
Well that's my method 1 suggest above right? I didn't fancy that.

No, not really. Interfaces really just have stub methods in the first place.


Grey Alien(Posted 2013) [#13]
@muddy_shoes I see what you mean but I always add new functionality (like playing sound) to extended classes. Didn't know that was bad OOP. But I'm not an expert.

@therevills: OK I see what you mean.


muddy_shoes(Posted 2013) [#14]
@greyalien

It's not about adding functionality it's about encompassing the possibility behaviours/functions/features. That's why I tried to clarify the difference between can and does.

To try and make something concrete here, I'll assume that your base class is some form of Actor, GameObject, GameEntity or similar. There's nothing wrong with that base class not playing any sound but it's contradictory to take a view that it represents something that cannot play sound and then to add that functionality later. It's that contradiction that's causing your issues where you both want to operate via polymorphism on a consistent base interface and also avoid adding things to that interface that the base class doesn't directly implement. Something about cake comes to mind.


wiebow(Posted 2013) [#15]
This is why I love component based game entities. It gets rid of all these potentionally complicated issues and refactoring.


Shinkiro1(Posted 2013) [#16]
Right, with components you could do something like:

[monkeycode]
entity.RegisterComponent(New SoundComponent)
[/monkeycode]

The idea is, that you can feed your entity every behavior you want to and remove/change it (at runtime if you want).


Grey Alien(Posted 2013) [#17]
@muddy_shoes Good explanation thanks.

@weibow and Shinkiro1 Sounds cool, I've never done that in my games, although I've scripted for another game that did use that system.


wiebow(Posted 2013) [#18]
I might port my artemis port to monkey, but I ran into the problem that Monkey does not have a Long integer. Limits the amount of bits available for component types. Oh well.