Requiring Child Classes to call base.Foo() in overrides - c#

I'm working on a Unity project which uses a good amount of inheritance. I have an abstract base class whose methods I want its children to always call (e.g. Awake).
I haven't worked with attributes much - is there a way to add an attribute to my ABC's Awake method which causes the child-class to log an error if they override Awake() without calling base.Awake() in its implementation?
Thanks!

You could something like this:
public class A
{
public void Awake()
{
Console.WriteLine("Everybody does X on awake");
AwakeExtra();
}
public virtual void AwakeExtra() => Console.WriteLine("'A' also does A on awake");
}
public class B : A
{
public override void AwakeExtra() => Console.WriteLine("'B' also does B on awake");
}

Related

I'm currently doing a unity 3d combat course and i'm stuck on this

This won't go away now matter what i try, even though i have done everything according to the course i'm following.
'Inputreader' does not implement interface member 'Controls.IPlayerActions.OnDodge(InputAction.CallbackContext)'
Here is the code
public class Inputreader : MonoBehaviour, Controls.IPlayerActions
{
private Controls controls;
public event Action jumpEvent;
public event Action DodgeEvent;
private void Start()
{
Controls = new Controls();
Controls.Player.setCallbacks(this);
Controls.Player.Enable();
}
private void OnDestroy()
{
Controls.Player.Disable();
}
public void onJump(InputAction.CallbackContext context)
{
if (context.preformed)
{
jumpEvent?.Invoke();
}
}
public void onDodge(InputAction.CallbackContext context)
{
if (context.preformed)
{
DodgeEvent?.Invoke();
}
}
}
Firstly, let's get started with understanding the error, as that is the most important part of the problem.
'Inputreader' does not implement interface member 'Controls.IPlayerActions.OnDodge(InputAction.CallbackContext)'
What does this mean?
Let's start at the beginnning: The class InputReader apparently doesn't implement something. Why does it have to implement something?
Well, that is because of this line:
public class Inputreader : MonoBehaviour, Controls.IPlayerActions {
What does this line mean? It means that the class InputReader will have (Implement) all required methods and properties of the Interfaces/Classes MonoBehavior and Controls.IPlayerActions
In this case, IPlayerActions specify the following requirements:
Must have a public method OnJump which accepts InputAction.CallbackContext context as a parameter.
Must have a public method onDodge(InputAction.CallbackContext context) with the same sort of parameter.
Now back to the error, it specifies that this class is missing an implementation for OnDodge. Please note that everything in c# is case-sensitive. What does this mean?
public void onDodge is not the same as public void OnDodge.
What does the error specify?
Controls.IPlayerActions."OnDodge". What did you implement in your class? "onDodge". Do you see the difference?
Make sure the capitalization is correct for all implemented class members, or else you will get such errors.

Limit inheritance of intermediate abstract class

I have an abstract class, CreatureBehaviour, that provides a TakeTurn method. The goal of this is to decide what the creature should do, and it should provide its response via callback. This is because the response may require player input, so it shouldn't block other processes.
public abstract class CreatureBehaviour {
public abstract void TakeTurn (Action<TurnAction> response);
}
Inheriting from this, the PlayerControl class stores the response callback for later decision-making. Most of its content isn't relevant, but ultimately it must invoke response when the player does something.
public class PlayerControl : CreatureBehaviour {
Action<TurnAction> responseCallback;
public override void TakeTurn(Action<TurnAction> response) {
responseCallback = response;
}
// Various UI callbacks that can send something to "responseCallback" when appropriate.
}
And all non-player creatures need to be able to send a callback too. For safety, I want to ensure that a callback is always hit, so I've created an abstract NonPlayerControl class that ensures a response:
public abstract class NonPlayerControl : CreatureBehaviour {
protected abstract TurnAction TurnResponse ();
public override void TakeTurn (Action<TurnAction> response) {
response (TurnResponse ());
}
}
With this, all of my non-player creature behaviours can derive from NonPlayerControl and simply implement TurnReponse(). The compiler guarantees that all their scripts will return a response, rather than leaving the callback hanging. Note that PlayerControl can't implement TurnResponse() because it would need to guarantee an immediate return, and that would block other processes.
So I want to derive other classes from NonPlayerControl and maybe from PlayerControl, but I don't want to accidentally derive another class from CreatureBehaviour and risk missing the callback.
Is there any way I can "sort of seal" CreatureBehaviour so that it can only have these two direct children and prevent any others? If not, is there a better pattern I could be using here?
There's nothing you could do for this in a "normal" way, but there's one option you could consider...
If you give your CreatureBehavior class just a private constructor, then nest PlayerBehavior and NonPlayerBehavior within that class, they will have access to the private constructor but no other classes will... so no other classes could derive from CreatureBehavior.
A simpler solution would be to:
Document in CreatureBehavior that it shouldn't be subclassed directly
Write unit tests to validate that there aren't any other subclasses
That can only test your code rather than code in other assemblies, of course. If you don't need these from other assemblies, then make the classes internal instead of public. Even if you need all the classes to be public, you could include a no-op abstract internal method that's implemented in PlayerBehavior and NonPlayerBehavior - that will stop classes outside your assembly from deriving from CreatureBehavior as they can't implement the internal abstract method.
Just a quick idea, without further testing: Could you use a generic to do the restriction?
public abstract class CreatureBehaviour<T> where T : IPlayerControl, INonPlayerControl {
// ...
}
And then use it in the following way:
public abstract class NonPlayerControl : CreatureBehaviour<NonPlayerControl>, INonPlayerControl {
// ...
}
public abstract class PlayerControl : CreatureBehaviour<PlayerControl>, IPlayerControl {
// ...
}
It is sort of a hack, but it might work for your case.
You cannot prohibit inheritance from the CreatureBehavoiur class but you can limit access to TakeTurn methods by combining internal, sealed and protected access and place it in the separate assembly:
public abstract class CreatureBehaviour
{
protected abstract void TakeTurn(Action<TurnAction> response);
}
public class PlayerControl : CreatureBehaviour
{
private Action<TurnAction> responseCallback;
protected override void TakeTurn(Action<TurnAction> response)
{
responseCallback = response;
}
internal void TurnByPlayer(Action<TurnAction> response)
{
TakeTurn(response);
}
// Various UI callbacks that can send something to "responseCallback" when appropriate.
}
public abstract class NonPlayerControl : CreatureBehaviour
{
protected abstract TurnAction TurnResponse();
protected override void TakeTurn(Action<TurnAction> response)
{
response(TurnResponse());
}
internal void TurnByNonPlayer(Action<TurnAction> response)
{
TakeTurn(response);
}
}
public sealed class CreatureStearing
{
public void Turn(PlayerControl control)
{
control.TurnByPlayer((action) => {});
}
public void Turn(NonPlayerControl control)
{
control.TurnByNonPlayer(action => {});
}
}
Now you can inherit from PlayerControl, NonPlayerControl, and even CreatureBehaviour in other assemblies, but you cannot use TakeTurn methods for any class intances other than PlayerControl and NonPlayerControl that are in separate assemblies:
public class SomeTest1 : PlayerControl
{
protected override void TakeTurn(Action<TurnAction> response)
{
base.TakeTurn(response);
}
}
public class SomeTest2 : NonPlayerControl
{
protected override TurnAction TurnResponse()
{
throw new NotImplementedException();
}
protected override void TakeTurn(Action<TurnAction> response)
{
base.TakeTurn(response);
}
}
public class SomeTest3 : CreatureBehaviour
{
protected override void TakeTurn(Action<TurnAction> response)
{
throw new NotImplementedException();
}
}
....
var t1 = new SomeTest1();
var t2 = new SomeTest2();
var t3 = new SomeTest3();
var creatureStearing = new CreatureStearing();
creatureStearing.Turn(t1);
creatureStearing.Turn(t2);
creatureStearing.Turn(t3); // 'Cannot resolve method 'compile error here
Of course you can pass this limitation by declaring internal access for your assembly, but it requires to implement something like CreatureStearing (well some efforts) but other party in this case will know for sure this is a hack.

c# inheritance of base class to template

I want to write a framework which needs to implement a few functions. Now I need to access the base class functions from the framework, which does not work.
I need to inherit form a given class "Master"
public class MyClass : Master
{
protected override void Initialize() {
FunctionInMaster();
VariableInMaster = true;
}
}
Now I simply want to create a class that can be derived and implements Master functions.
public class MyFrameworkClass
{
// framework override
public void whatever()
{
FunctionInMaster();
VariableInMaster = true;
}
}
public class MyClass : Master
{
protected override void Initialize() {
whatever();
FunctionInMaster();
VariableInMaster = true;
}
}
How do I do that without instantiating "MyFrameworkClass" and passing a pointer of "this" to MyFrameworkClass?
You can never have multiple inheritance in C# (and it's a very good thing, multiple inheritance is a nightmare), but you can invoke methods from other classes, or even have some composition.
public static class MyFrameworkClass
{
// framework override
public static void whatever(Master master)
{
master.FunctionInMaster();
master.VariableInMaster = true;
}
}
public class MyClass : Master
{
protected override void Initialize()
{
MyFrameWorkClass.whatever(this);
FunctionInMaster();
VariableInMaster = true;
}
}
Don't try to do too many things with inheritance. Inheritance is a powerful tool, but not an universal one. Often composition is better suited to tackle a specific problem.
You could also have multiple levels of inheritance, if you need to access protected methods and you know you will reuse this code in other derived classes.
public class MyFrameworkClass : Master
{
// framework override
protected void whatever()
{
FunctionInMaster();
VariableInMaster = true;
}
}
public class MyClass : MyFrameworkClass
{
protected override void Initialize()
{
whatever();
FunctionInMaster();
VariableInMaster = true;
}
}
Although you could change inheritance to be Master -> MyFrameworks -> MyClass, that is less advisable. Is the intention to make sure deriving classes implement specific methods - in that case consider adding abstract methods to Master. If you are unable to alter Master, you can change MyFrameworks to be an interface rather than a class. MyClass can inherit multiple interfaces, but only one class.
I need to access the base class [instance] functions from the framework
To call instance methods you need an instance. There are three ways to do that:
Inherit form the class and use this - you have already stated that you can't do this.
Accept an instance of the base class and call methods on it - you have stated that you don't want to do this.
Create an instance of the class and call methods on it.
Now static methods are different - you do not need an instance, but they can only use static fields, which would be shared across all instances of the class. Since you use a non-static property in the base class, it's safe to assume that static is not an option, so you're stuck with one of the three options above.

Order of execution in Abstract Class

I came across a posting where it is said that MustBeCalled() method will get called if we have the Abstract class do the calling in this manner.
public abstract class AbstractClass
{
public void PerformThisFunction()
{
MustBeCalled();
AbstractMethod();
}
public void MustBeCalled()
{
//this must be called when AbstractMethod is invoked
}
//could also be public if desired
protected abstract void AbstractMethod();
}
public class ImplementClass : AbstractClass
{
protected override void AbstractMethod()
{
//when called, base.MustBeCalled() must be called.
//how can i enforce this?
}
}
But how does MustBeCalled() method get called?
In what order things are called here?
If you call PerformFunction() first, then everything will execute in the intended order, where that order is specified in the order of the lines of code in PerformFunction(). If you call AbstractMethod() directly, there's no guarantee that MustBeCalled() will ever be called. However, I notice that you have AbstractMethod() marked as protected, which means that outside consumers of your class will not be able to call it directly. They'll have to use PerformFunction() -- this is good, as there is now only one public way to invoke your internal methods, and that way guarantees the order that you need.
In truth, there is a level at which you can only guarantee that things happen by choosing to write code to make them happen. You can't, for example, guarantee that code is going to implement a game of Tetris except by actually writing that code and choosing to implement it in such a way that it produces Tetris behavior. The type system and the public/protected/private modifiers can help some by preventing some misuse (as your internals are not accessible and thus cannot be invoked by consumers of your module), but they can only go so far. This is such a case.
You cannot enforce how an implementation to call a method when invoked. The implementation could do its own thing entirely, or do nothing.
public class ImplementClass : AbstractClass
{
protected override void AbstractMethod()
{
// this is a perfectly valid implementation
}
}
A better implementation could be.
public abstract class AbstractClass
{
public void PerformThisFunction()
{
MustBeCalled();
AbstractMethod();
}
private void MustBeCalled()
{
}
protected virtual void AbstractMethod()
{
MustBeCalled();
}
}
This way refactoring tools will at least create the desired boilerplate code:
public class ImplementClass : AbstractClass
{
protected override void AbstractMethod()
{
base.AbstractMethod();
}
}
However, the person overriding AbstractMethod still needs to call base.AbstractMethod, this is not enforced by the compiler at all.

C# - using polymorphism in classes I didn't write

What is the best way to implement polymorphic behavior in classes that I can't modify? I currently have some code like:
if(obj is ClassA) {
// ...
} else if(obj is ClassB) {
// ...
} else if ...
The obvious answer is to add a virtual method to the base class, but unfortunately the code is in a different assembly and I can't modify it. Is there a better way to handle this than the ugly and slow code above?
Hmmm... seems more suited to Adapter.
public interface ITheInterfaceYouNeed
{
void DoWhatYouWant();
}
public class MyA : ITheInterfaceYouNeed
{
protected ClassA _actualA;
public MyA( ClassA actualA )
{
_actualA = actualA;
}
public void DoWhatYouWant()
{
_actualA.DoWhatADoes();
}
}
public class MyB : ITheInterfaceYouNeed
{
protected ClassB _actualB;
public MyB( ClassB actualB )
{
_actualB = actualB;
}
public void DoWhatYouWant()
{
_actualB.DoWhatBDoes();
}
}
Seems like a lot of code, but it will make the client code a lot closer to what you want. Plus it'll give you a chance to think about what interface you're actually using.
Check out the Visitor pattern. This lets you come close to adding virtual methods to a class without changing the class. You need to use an extension method with a dynamic cast if the base class you're working with doesn't have a Visit method. Here's some sample code:
public class Main
{
public static void Example()
{
Base a = new GirlChild();
var v = new Visitor();
a.Visit(v);
}
}
static class Ext
{
public static void Visit(this object b, Visitor v)
{
((dynamic)v).Visit((dynamic)b);
}
}
public class Visitor
{
public void Visit(Base b)
{
throw new NotImplementedException();
}
public void Visit(BoyChild b)
{
Console.WriteLine("It's a boy!");
}
public void Visit(GirlChild g)
{
Console.WriteLine("It's a girl!");
}
}
//Below this line are the classes you don't have to change.
public class Base
{
}
public class BoyChild : Base
{
}
public class GirlChild : Base
{
}
I would say that the standard approach here is to wrap the class you want to "inherit" as a protected instance variable and then emulate all the non-private members (method/properties/events/etc.) of the wrapped class in your container class. You can then mark this class and its appropiate members as virtual so that you can use standard polymorphism features with it.
Here's an example of what I mean. ClosedClass is the class contained in the assembly whose code to which you have no access.
public virtual class WrapperClass : IClosedClassInterface1, IClosedClassInterface2
{
protected ClosedClass object;
public ClosedClass()
{
object = new ClosedClass();
}
public void Method1()
{
object.Method1();
}
public void Method2()
{
object.Method2();
}
}
If whatever assembly you are referencing were designed well, then all the types/members that you might ever want to access would be marked appropiately (abstract, virtual, sealed), but indeed this is unfortunately not the case (sometimes you can even experienced this issue with the Base Class Library). In my opinion, the wrapper class is the way to go here. It does have its benefits (even when the class from which you want to derive is inheritable), namely removing/changing the modifier of methods you don't want the user of your class to have access to. The ReadOnlyCollection<T> in the BCL is a pretty good example of this.
Take a look at the Decorator pattern. Noldorin actually explained it without giving the name of the pattern.
Decorator is the way of extending behavior without inheriting. The only thing I would change in Noldorin's code is the fact that the constructor should receive an instance of the object you are decorating.
Extension methods provide an easy way to add additional method signatures to existing classes. This requires the 3.5 framework.
Create a static utility class and add something like this:
public static void DoSomething(this ClassA obj, int param1, string param2)
{
//do something
}
Add a reference to the utility class on the page, and this method will appear as a member of ClassA. You can overload existing methods or create new ones this way.

Categories

Resources