In a simplified version, I have the following:
abstract class Days
{
private readonly int _amount;
protected virtual void UpdateAmount()
{
Proccess();
}
protected virtual void Process()
{
_amount += 1;
}
}
The problem is I need to create a class which inherits from Days, in which I need to change the functionality of UpdateAmounts() but still use the same functionality from Process(). Since Process uses a private field, is there anyway to do this without just copying and pasting the code from Process() into my child class? It wont let me use base.Process() because the method references a private field.
You will be able to use base.Process() because it is protected, it doesn't matter if it uses private fields
class MyClass : Days
{
protected override void UpdateAmount()
{
base.Process();
}
}
This code works
Related
I'm building some classes within unity to define the mechanics individually, and transition between each for easier and cleaner code.
What I wanna know, is when should I be using a constructor to pass variables around, and when to use protected variables. What are the pros and cons of each, and what should I know about them? Also what should I lean towards, like what's practical?
Previously I'd pass these variables into the PlayerState constructor, then in my classes that extend from my PlayerState would follow suit. But if they're protected variables I don't need to pass them into the constructor to access them, and I was wondering what should I do?
using UnityEngine;
The new way I'm doing it:
public class PlayerState
{
//protected Core Core;
protected Player player;
protected PlayerStateMachine StateMachine;
protected PlayerData playerData;
private string currentAnimation;
protected float StartTime; // Start time gets set everytime we're in a state, that way we have a reference for how long we've been in any state (good for mechanics)
protected bool isAnimationFinished;
protected bool isExitingState; // Very useful, if you run through if/else conditionals in a superState, the substate may still run, and both end up calling a change state. This will stop this from happening
public PlayerState(string currentAnimation)
{
this.currentAnimation = currentAnimation;
}
public virtual void Enter() { }
public virtual void Exit() { }
public virtual void LogicUpdate() { }
public virtual void PhysicsUpdate() { }
public virtual void DoChecks() { }
}
The Old Way:
public class PlayerState
{
protected Core Core;
protected Player player; // protected means private but shared between components that inherit the class
protected PlayerStateMachine StateMachine;
protected PlayerData playerData;
private string currentAnimation;
protected float StartTime; // Start time gets set everytime we're in a state, that way we have a reference for how long we've been in any state (good for mechanics)
protected bool isAnimationFinished;
protected bool isExitingState; // Very useful, if you run through if/else conditionals in a superState, the substate may still run, and both end up calling a change state. This will stop this from happening
public PlayerState(Player player, PlayerStateMachine stateMachine, PlayerData playerData, string currentAnimation)
{
this.player = player;
this.StateMachine = stateMachine;
this.playerData = playerData;
this.currentAnimation = currentAnimation;
Core = player.Core;
}
// So now we code out the functions for each state
// Every state must have an enter and exit function, as well as an update and fixedUpdate function
// We're naming the update function as "LogicUpdate", and fixedUpate as "PhysicsUpdate"
public virtual void Enter() // virtual means this function may be overriden from classes that inherit this class
{
DoChecks();
player.Anim.SetBool(currentAnimation, true);
StartTime = Time.time;
isAnimationFinished = false;
isExitingState = false;
//Debug.Log("Current Animation: " + currentAnimation);
}
public virtual void Exit()
{
player.Anim.SetBool(currentAnimation, false);
isExitingState = true;
}
The way I applied it to other classes the old way:
public class PlayerGroundedState : PlayerState
{
protected Vector2 input;
protected bool jumpInput;
private bool grabInput;
private bool dashInput;
private bool isTouchingGround;
private bool isTouchingWall;
protected bool willCollideWithCeiling;
public PlayerGroundedState(Player player, PlayerStateMachine stateMachine, PlayerData playerData, string currentAnimation) : base(player, stateMachine, playerData, currentAnimation)
{
}
public override void Enter()
{
base.Enter();
player.JumpState.ResetAmountOfJumpsLeft();
player.DashState.ResetCanDash();
}
public override void Exit()
{
base.Exit();
}
I don't have to pass player into the constructor of PlayerState and PlayerGroundedState to access it if it's protected. What should I do though, which method is the proper way to handle the variables, also which is better for my cpu?
This is just a question related to OOP. Unity is not needed to be considered.
A constructor let you create an object instance and initialize the members of the object at the same time. If there are some immutable members (i.e. they will never be changed after construction), you may need to initialize them in constructors, and you may add the keyword readonly to the members. If you don't need to initialize any member with passing parameter(s) when the instance is created, there is no need to have a custom constructor (unless you want to hide the default constructor).
The access modifier protected makes the member accessible only in code in the same class, or in a class that is derived from that class. If you need to access the member in other places, you still need do it via public/internal methods such as setters and getters, or make it public/internal.
In your case, I think a constructor is needed to initialize the members such as player when a PlayerState instance is created.
I am working on a simple GUI framework, and I faced a problem calling protected virtual methods.
Here is the IKeyboardInputListenerService interface of service I use to receive keyboard events and the Control class that represents a base for all my GUI controls. The internal method is the one being refactored.
public interface IKeyboardInputListenerService
{
event EventHandler<KeyboardEventArgs> KeyPressed;
}
public abstract class Control
{
public IKeyboardInputListenerService KeyboardInputListenerService { get; }
protected Control(IKeyboardInputListenerService keyboardInputListenerService) =>
KeyboardInputListenerService = keyboardInputListenerService;
public event EventHandler<KeyboardEventArgs> KeyPressed;
/* protected */ internal virtual void OnKeyPressed(object sender, KeyboardEventArgs args)
{
if (enabled && visible && focused && !args.Suppressed)
{
KeyPressed?.Invoke(sender, args);
args.Suppressed = true;
}
}
public void Activate() =>
KeyboardInputListenerService.KeyPressed += new EventHandler<KeyboardEventArgs>(OnKeyPressed);
}
I also created a ContainerControl class that is supposed to contain child controls(like the Panel or GroupBox in Windows Forms) and that overrides the virtual method:
public abstract class ContainerControl : Control
{
private readonly ObservableCollection<Control> controls;
protected ContainerControl(IKeyboardInputListenerService keyboardInputListenerService)
: base(keyboardInputListenerService) =>
controls = new ObservableCollection<Control>();
/* protected */ internal override void OnKeyPressed(object sender, KeyboardEventArgs args)
{
foreach (Control control in controls)
control.OnKeyPressed(sender, args);
base.OnKeyPressed(sender, args);
}
}
Problem is, I cannot decide which modifier to use for methods such as OnKeyPressed. I wanted to make them protected, but it causes a compiler error:
Error CS1540 Cannot access protected member 'Control.OnKeyPressed(object, KeyboardEventArgs)' via a qualifier of type 'Control'; the qualifier must be of type 'ContainerControl' (or derived from it)
I can make them public, but I do not really think it is a good idea, because there is no reason for it except for resolving the problem caused by a cross-hierarchy call. I made them internal, but there is also a drawback: if anyone will want to create a user control, they will not be able to receive events, so the control will be useless.
The question is how to get access from a derived class to virtual methods of the base class without making the methods public-accessed.
Use protected internal
protected internal virtual void OnKeyPressed(object sender, KeyboardEventArgs args)
{ ... }
The documentation says:
protected internal The type or member can be accessed by any code in the assembly in which it is declared, or from within a derived class in another assembly.
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.
I'm working with a binary that contains an object and the base class it extends. I want to instantiate the object, but for it to use my own implementation of the base class. I can see in the base class to know what methods I need t extend.
The problem is that the base class implements a method called "WriteFeed" that expects network connections and writes data out to a network stream. I would like it to use my implementation so WriteFeed can instead dump data to console.
I cannot change the existing binaries, only the way I consume and instantiate it.
My only suggestion is to use a composite approach. I'm not sure if this will meet your need or you have visibility access, but it may work.
public class SomeBaseClassInSomeBinary
{
protected virtual void Method1(...) {}
protected virtual void WriteFeed (...) {}
}
public class SomeClassInSomeBinary: SomeBaseClassInSomeBinary
{
protected override void Method1(...) { base.Method1(...); }
protected override void WriteFeed (...) { base.WriteFeed (...); }
}
// **** your code
public class MyCode: SomeBaseClassInSomeBinary
{
private SomeClassInSomeBinary Composite = new SomeClassInSomeBinary();
protected override void Method1(...) { Composite.Method1(...); }
protected override void WriteFeed (...) { your implementation }
}
}
All you need to do is now use your object instead.
Hope this helps.
I have been trying to work out how to call a method in a different class. Both classes are created dynamically at run-time. Most of the issues I have seen here relate to inheritance, which is different from what I have (I think.)
I am still fairly new to C#, and am trying to test some concepts out.
The first class is something like this:
public class Record
{
CustomPanel _panel;
public void recordFunc(){}
}
The internally created class has something like this:
public class CustomPanel : Panel
{
List<Control> _myControls = new List<Control>;
// _myControls[0] += new EventHandler(myFunc);
public void myFunc(object sender, EventArgs e)
{
// parentClass.recordFunc();
}
}
My objective is to create a Record at run-time from a database call. At that point, it creates a Panel (from my CustomPanel class) that gets added to a FlowLayoutControl. When events are fired from the panel's internal controls, I need to have it update parts of the parent Record class.
Any help is greatly appreciated.
I'm not 100% sure what you're asking, but it seems you want to know how to call a function on a class, when you don't know the class type at runtime, but it could be one or many record types. Is that correct?
If so, a way to cleanly achieve the above is to implement an interface on your derived types and call the interface method. For instance, if you have multiple "Record" classes and don't know the type at runtime, try the following:
public interface IRecord
{
void RecordFunc();
}
public class ARecord : IRecord
{
public void RecordFunc()
{
Console.WriteLine("ARecord.RecordFunc");
}
}
public class AnotherRecord : IRecord
{
public void RecordFunc()
{
Console.WriteLine("AnotherRecord.RecordFunc");
}
}
public class CustomPanel : Panel
{
private IRecord _parentRecord;
// Where parentRecord could be ARecord or AnotherRecord
public class CustomPanel(IRecord parentRecord)
{
_parentRecord = parentRecord;
}
public void MyFunc(object sender, EventArgs e)
{
_parentRecord.RecordFunc();
}
}
If that's not what you're looking for, please clarify.
There is no magic instance of the Record class available from within a CustomPanel just because a Record instance contains a CustomPanel. You'll have to set up such a relationship yourself. E.g.
public class Record
{
CustomPanel _panel;
public CustomPanel panel
{
get { return _panel; }
set { _panel = value; _panel.parent = this; }
}
public void recordFunc(){}
}
public class CustomPanel : Panel
{
public Record parent { get; set; }
public void myFunc(object sender, EventArgs e)
{
parent.recordFunc();
}
}