If I extend a c# interface, can I eat a call? - c#

In this question I mention Unity3D, but applies generally in c#.
Unity3D has an Interface that looks like this ..
public class SomeRobot:MonoBehaviour, IPointerDownHandler
{
public void OnPointerDown(PointerEventData data)
{
Debug.Log("Gets called whenever someone touches the screen...");
}
No problem so far.
I make my own interface..
public interface IFUHandler:IPointerDownHandler
{
void OnBlah (PointerEventData data);
}
Assume I have a daemon or whatever that calls OnBlah for consumers of the interface.
public class SomeRobot:MonoBehaviour, IFUHandler
{
public void OnBlah(PointerEventData data)
{
Debug.Log("Gets called when blah happens...");
}
No problem so far. BUT
public class SomeRobot:MonoBehaviour, IFUHandler
{
public void OnBlah(PointerEventData data)
{
Debug.Log("Gets called when blah happens...");
}
public void OnPointerDown(PointerEventData data)
{
Debug.Log("this DOES still get called also...");
}
In fact, OnPointerDown still gets called. Which makes sense.
BUT .... is there a way for my Interface to eat the calls to OnPointerDown?
So that a consumer subscribing to IFUHandler in fact does NOT get the calls to OnPointerDown?
(But of course gets my OnBlah calls.)
Or am I just suffering "TMIOOK" thinking? (Tied Myself In OO Knots thinking :) )

Simple answer: No.
Possible solutions:
Don't inherit IPointerDownHandler when you don't need it. Why do you need this interface if you aren't going to use it?
Create a Sealed Abstract class with a non-virtual method
public class BaseFUHandler : MonoBehaviour, IFUHandler
{
public abstract void OnBlah(PointerEventData data);
public void OnPointerDown(PointerEventData data)
{
//Gets called, but nothing hapends.
}

Related

Explanation on how this works?

I have a pretty basic understanding of inheritance and so when using it there are a few moments like this where I find it difficult to understand what's fully happening and it probably doesn't help that I'm most likely not using it properly.
Anyways though I have these 3 classes
public abstract class EffectBase
{
public enum EffectType
{
harm,
help,
self
}
public EffectType type;
public float duration;
public void Activate()
{
Debug.Log("Activating effect");
ApplyEffect();
}
public abstract void ApplyEffect();
public abstract void End();
}
public class Player : MonoBehaviour
{
public List<EffectBase> effects = new List<EffectBase>();
void Update()
{
if (Input.GetKeyDown("q"))
{
Debug.Log("Q pressed");
AddEffect(new SpeedEffect());
}
}
public void AddEffect(EffectBase effect)
{
Debug.Log("Adding effect");
effects.Add(effect);
effect.Activate();
}
}
public class SpeedEffect : EffectBase
{
public override void ApplyEffect()
{
Debug.Log("Speed effect applied");
}
public override void End()
{
Debug.Log("Speed effect ended");
}
}
When I call the AddEffect method I pass a new instance of SpeedEffect (I think it's an instance) as the parameter and then in the AddEffect method I call the Activate method from it, however, in the SpeedEffect class, it doesn't have or override that method so I'm assuming it goes to the base class which does have it and continues and now here's where I get confused in the Activate method it calls the ApplyEffect method, but how does it know to call the one in the SpeedEffect class?
Despite not having an override for Activate() that method still exists in the SpeedEffect class, you just didn't need to write any code for it since its the same code so theres no need to duplicate it.
The code for Activate() calls the ApplyEffect() method for whatever class its being called from. In this case: EffectBase.Activate() and SpeedEffect.Activate() have the same code in terms of reading it, but they are not the same; EffectBase.ApplyEffect() and SpeedEffect.ApplyEffect() are two different methods and each are called from their respective classes.

Looking for a better way to extend methods

I'm working on a hobby project in Unity. I have MonoBehaviour scripts for my characters that use component objects for each behavior the character has. When I create new characters, I inherit a new class from the base class for whichever component behaves differently.
When certain triggers occur, I send characters back to their initial state by calling a Reset() method exposed by the base class that sets fields back to their initial values. I'm wondering how to send that call down through the inheritance chain. Right now, the base class has a protected virtual ChildReset() that gets called in Reset() and does nothing by default. If child classes have fields to reset, they override this method. It feels like a really awkward way of doing it.
I like the idea of implementing something similar to the messaging system Unity uses. If a monobehavior doesn't use the Update() message, then the class just doesn't define an update. It eliminates unnecessary calls. I have no idea how I would do something like that.
Any thought invested in this is much appreciated! I've written out the way my project is structured below just in case these details are useful for answers.
public class Character : MonoBehaviour
{
private Motion motionController;
private Interaction characterInteractionController;
//etc
private void Update()
{
motionController.DoStuff();
characterInteractionController.DoStuff();
}
private void Reset()
{
motionController.Reset();
characterInteractionController.Reset();
}
private void OnEnable() => ResetTrigger.OnReset += Reset;
private void OnDisable() => ResetTrigger.OnReset -= Reset;
}
public class Motion : Component {}
public class Interaction : Component {}
public abstract class Component
{
public void Reset()
{
/* set fields to default values */
ChildReset();
}
protected virtual void ChildReset() { }
public abstract void DoStuff();
}
There is no need to send a call down through the inheritance chain. You do not have two different objects. An object of the child class contains everything declared in the base class. Why not directly make Reset() virtual?
public abstract class Character : MonoBehaviour
{
public virtual void Reset()
{
...
}
}
public class ChildCharacter : Character
{
// If ChildCharacter has stuff to reset, override this method, otherwise don't!
public override void Reset()
{
base.Reset(); // Call this to reset stuff from the base class.
//TODO: reset child stuff.
}
}
If Reset is overridden in the child class, then calling Reset will call ChildCharacter.Reset() even if called on a variable statically typed as Character.
Character c = new ChildCharacter();
c.Reset(); // calls ChildCharacter.Reset() when overridden
If Reset is not overridden in the child class, then calling Reset will call Character.Reset() even if called on a ChildCharacter.
ChildCharacter child = new ChildCharacter();
child.Reset(); // calls Character.Reset() when not overridden.

How can I manage different weapons in manager script?

I'm making my rpg game in unity. As I need a lot of different weapons, I tried to make a script for each weapons. Then instead of enacting the Attack function in each weapon's object, I wanted to controll them in other class such as WeaponManager for some reason.
However, I got no idea how to manage variety of classes. It doesn't seem efficient to write all the codes for each classes, such as
if((gameObject).name=="Wand")
gameObject.Getcomponent<Wand>().Attack();
else if((gameObject).name=="Sword")
gameObject.Getcomponent<Sword>().Attack();
... and so on.
In other way, I also thought of SendMessage function, but it doesn't seem like efficient as well.
I'm wodering how can I solve this problem. Which method can I use?
Classical example use case for object oriented programming:
Inheritance!
Use a shared parent class both inherit from and either implement the method virtual with a shared default behavior the inheriting classes can overwrite/extend or make it abstract so inheriting classes have to implement it.
public abstract class Weapon : MonoBehaviour
{
public abstract void Attack();
// alternatively implement some default behavior
// in this case the child classes can but don't have to override this
//public virtual void Attack()
//{
// Debug.Log("Harr Harr .. but I'll do nothing else!", this);
//}
}
and then
public class Wand : Weapon
{
public override void Attack()
{
...
}
}
and
public class Sword : Weapon
{
public override void Attack()
{
...
}
}
then simply go
gameObject.GetComponent<Weapon>().Attack();

How to execute an async method inside an abstract class from another call back method in a different class

I have a concrete class call AncSubscriberWrapper and it has a call back method
public Task OnUnshownCounterUpdatedAsync(long counter)
{
return Task.CompletedTask;
}
and also I have an abstract class call BasePageViewModel and it has an async method
protected async void GetUnseenNotificationsCount()
{
UnseenNotificationCount = await m_ancSubscriberWrapper.TryGetNotificationCountAsync(NotificationStatus.Delivered | NotificationStatus.Created);
}
Classes paths are like below inside the project.
./src/Visit.Common/Services/AncSubscriberWrapper.cs
./src/Visit.Common/ViewModels/PageViewModels/BasePageViewModel.cs
What I need is to execute the GetUnseenNotificationsCount() method from OnUnshownCounterUpdatedAsync() method.
How can I do that?
This is one way I was able to reach my goal. I am not sure this is the right way of doing this though.
How I achieved my goal is using an EventHandler.
Create an interface (IAncSubscriberWrapper) for AncSubscriberWrapper class
public interface IAncSubscriberWrapper
{
event EventHandler UnshownNotificationCounterUpdated;
}
and implements it like below
public class AncSubscriberWrapper : NotificationCenterFacade, IAncSubscriberWrapper
Then implement the interface member inside the AncSubscriberWrapper class
public event EventHandler UnshownNotificationCounterUpdated;
and also invoke method inside the OnUnshownCounterUpdatedAsync method
public Task OnUnshownCounterUpdatedAsync(long counter)
{
UnshownNotificationCounterUpdated?.Invoke(this, null);
return Task.CompletedTask;
}
Then go to BasePageViewModel and register and unregister listeners.
public void Initialize()
{
m_ancSubscriberWrapper.UnshownNotificationCounterUpdated += OnUnshownNotificationCounterUpdated;
}
public void Teardown()
{
m_ancSubscriberWrapper.UnshownNotificationCounterUpdated -= OnUnshownNotificationCounterUpdated;
}
Since BasePageViewModel is an abstract class, which ever the concrete class that use it, will override the methods. (Following code snippet is not directly related to this question, but for understanding the design on my code basis)
/*
* BaseContainerViewController is only accepting TPageViewModel generic type of classes only.
* TPageViewModel inherits BasePageViewModel and BaseContainerViewController inherits BaseViewController
* That's what following line is all about
*/
public abstract class BaseContainerViewController<TPageViewModel> : BaseViewController where TPageViewModel : BasePageViewModel
and
public class WardListViewController : BaseContainerViewController<WardListPageViewModel>
Back to the final part of the answer. Add following method inside BasePageViewModel class and that will complete the process.
protected virtual void OnUnshownNotificationCounterUpdated(object sender, EventArgs eventArgs)
{
GetUnseenNotificationsCount();
}

Prevent/Generate warning if subclass calls an overriden member

Given the following pseudo C# code:
public abstract class Worker
{
public void DoWork()
{
Prepare();
Work();
Cleanup();
}
protected abstract void Work();
}
With this design, it is possible, that a derived class (which overrides the Work() method) calls the Work() method directly.
I'm looking for design tips on how to prevent any subclass to do this call, or at least generate a compiler warning.
Why I want to do this?
The Worker actually dispatches the Work() to another thread. DoWork() takes care about the locking.
I know, this is weird. The Work()-body might just consist of a method call to DoMyWork() and the object might call DoMyWork() somewhere else. It's impossible to intercept that.
Anyways. I appreciate any thoughts on that issue.
Thanks to Eris and Corey I think I figured it out. What about this way:
public abstract class Worker
{
public void DoWork()
{
if (Work != null)
{
Prepare();
Work();
Cleanup();
}
}
protected Action Work { private get; set; }
}
public class ImplWorker {
public ImplWorker() {
Work = //whatever
}
}
Still if he really wanted to he can store it somewhere else and stuff. But it goes as far as I can imagine.
If the Work is done using a resource (e.g. remote server, database connection), or it can be changed to be like that, then you could do it like this:
public interface IResource
{
}
public abstract class Worker
{
private class TheResource : IResource
{
// implement
}
public void DoWork()
{
Prepare();
var resObj = new TheResource();
Work(resObj);
// if needed, cleanup/dispose resObj here
Cleanup();
}
protected abstract void Work(IResource resourceObj);
}
This is somewhat of a hack, but you could change the method to be virtual, add a body which calls the new method, and then add an ObsoleteAttribute to it.
protected void DoWork()
{
// New method
}
[Obsolete("This method is deprecated.")]
protected virtual void Work()
{
DoWork();
}
Marking the method as virtual will prevent any existing child classes from breaking, since they were previously required to override Work().

Categories