Exposing methods of a class only to a Manager class? - c#

Let's say I have a Screen class. This class has few abstract methods like EnterScreen, ExitScreen that are protected.
I want to change screen only through a ScreenManager class but I cannot since both methods are protected.
If I make methods public, I can make a call to both methods in ScreenManager but then I expose them to other classes that accept Screen class as a parameter thus they can easily call Enter and Exit Screen.
Any idea of how can make a call only through ScreenManager and without exposing both methods to other classes? (Only ScreenManager can change screens)
Thanks in advance.
EDIT: #derHugo provided an answer that I should use namespaces and internal keyword, however, I've already tried this but it's not working as expected (methods of the internal class are still accessible in the namespace that is not the same as the Screen class). I'll provide code below and behavior I'm getting.
namespace Test
{
public abstract class Screen<T>
{
internal abstract void EnterScreen();
internal abstract void ExitScreen();
}
}
// Seperate class
namespace Test
{
public class SimpleScreen : Screen<UnityEngine.GameObject>
{
internal override void EnterScreen() { }
internal override void ExitScreen() { }
}
}
// This DOESN'T HAVE A NAMESPACE but I can STILL access the internal methods of the Screen class.
public class GameManager : MonoBehaviour, IInitializable<SimpleScreen>
{
public void Initialize(SimpleScreen screen)
{
// I CAN REFERENCE .Enter & ExitScreen methods here
}
}

One way to approach it is to inject your screenManager instance into your Screen and pass it these Actions that it has privileged access to:
public abstract class Screen<T>
{
protected abstract Action GetEnterScreenAction();
protected abstract Action GetExitScreenAction();
public Screen(ScreenManagerInterface screenManager)
{
screenManager.SetScreenActions(GetEnterScreenAction(), GetExitScreenAction());
}
}
public class SimpleScreen : Screen<UnityEngine.GameObject>
{
private void EnterScreen() { }
private void ExitScreen() { }
protected override Action GetEnterScreenAction() { return EnterScreen;}
protected override Action GetExitScreenAction() { return ExitScreen;}
public SimpleScreen(ScreenManagerInterface screenManager, ....) : base(screenManager) { }
}
public interface ScreenManagerInterface
{
void SetScreenActions(Action enterScreenAction, Action exitScreenAction);
}

A need to make some public methods available only to some other classes may indicate a design flaw in classes relationship. Maybe moving part of the responsibilities into ScreenManager itself could solve this problem.
As you declare Screen class abstract you intent on public or protected methods that can be overridden. So the only option for you to hide them from other classes is to make them protected.
And the only way to access protected members is from the class itself, derived or nested type.
You can make the class ScreenManger nested inside your Screen and it will default to private or make it public. If I understood your question correctly I made an example but without Unity.
I hope it can help
public interface IInitializable<T>
{
}
public class SimpleScreen : Screen<object>
{
protected override void EnterScreen() { }
protected override void ExitScreen() { }
public class ScreenManager
{
private SimpleScreen _simpleScreen;
public void Awake()
{
_simpleScreen.EnterScreen();
}
}
}
public abstract class Screen<T>
{
protected abstract void EnterScreen();
protected abstract void ExitScreen();
}
public class GameManager : IInitializable<SimpleScreen>
{
public void Initialize(SimpleScreen screen)
{
var screenManager = new SimpleScreen.ScreenManager();
screenManager.Awake();
screen.
}
}

Related

access protected members of another instance in derived class

Even though Iam in a derived class which should get me access to the derived protected members, I get the error
"Cannot access protected method 'BaseMethod' from here"
when trying to call other.BaseMethod();.
Can I get around this without having to make BaseMethod public? I also cannot make the method internal, since Base and Derived are in different assemblies.
class Base
{
protected void BaseMethod() { }
}
class Derived: Base
{
public void Doit(Base other)
{
other.BaseMethod();
}
}
You are using another class, as parameter, not the derived one.
in this case, the method should be public.
but have a look a this
How do you unit test private methods?
You can get around this by adding protected internal:
class Base
{
protected internal void BaseMethod() { }
}
class Derived : Base
{
public void Doit(Base other)
{
other.BaseMethod();
}
}
However, when inheritance is used then it can be called without any params. Let me show an example:
class Base
{
protected internal void BaseMethod() { }
}
class Derived : Base
{
public void Doit()
{
BaseMethod();
}
}

C# call method before override method

Good day,
I have a base class with a virtual method that needs to be overridden per implementation, but I would like to call the base method first before overriding.
Is there a way to accomplish this without having to actually call the method.
public class Base
{
public virtual void Method()
{
//doing some stuff here
}
}
public class Parent : Base
{
public override void Method()
{
base.Method() //need to be called ALWAYS
//then I do my thing
}
}
I cannot always rely that the base.Method() will be called in the override, so I would like to enforce it somehow. This might be a design pattern of some kind, any approach to accomplish the result will do.
One way is to define a public method in the base class, which calls another method that can be (or must be) overridden:
public class Base
{
public void Method()
{
// Do some preparatory stuff here, then call a method that might be overridden
MethodImpl()
}
protected virtual void MethodImpl() // Not accessible apart from child classes
{
}
}
public class Parent : Base
{
protected override void MethodImpl()
{
// ToDo - implement to taste
}
}
You can use the decorator design pattern, applying this pattern you can attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality:
public abstract class Component
{
public abstract void Operation();
}
public class ConcreteComponent1 : Component
{
public override void Operation()
{
//logic
}
}
public abstract class ComponentDecorator : Component
{
protected readonly Component Component;
protected ComponentDecorator(Component component)
{
Component = component;
}
public override void Operation()
{
if(Component != null)
Component.Operation();
}
}
public class ConcreteDecorator : ComponentDecorator
{
public ConcreteDecorator(Component component) : base(component)
{
}
public override void Operation()
{
base.Operation();
Console.WriteLine("Extend functionality");
}
}
Hope this helps!

Override abstract method, but keep method abstract?

I want to override an abstract method, but keep it abstract so derived classes are required to implement it themselves.
public abstract class ComponentController
{
public abstract void CreateCustomColumns();
}
public abstract class ClientComponentController : ComponentController
{
public override void CreateCustomColumns()
{
// All grids to do with clients should show these columns.
Grid.AddColumn("Client" ...
Grid.AddColumn("ClientLocation" ...
Grid.AddColumn("ClientPhoto" ...
}
}
public class ClientInvoicesComponentController : ClientComponentController
{
public override void CreateCustomColumns()
{
base.CreateCustomColumns();
// On top of the generic columns, I also want to show these.
Grid.AddColumn("InvoiceNumber" ...
Grid.AddColumn("InvoiceDate" ...
}
}
public class ClientCommunicationsComponentController : ClientComponentController
{
public override void CreateCustomColumns()
{
base.CreateCustomColumns();
// On top of the generic columns, I also want to show these.
Grid.AddColumn("CommunicationDate" ...
Grid.AddColumn("CommunicationType" ...
}
}
In this code, ClientInvoicesComponentController is not required to implement CreateCustomColumns() because this is not allowed:
public abstract class ClientComponentController : ComponentController
{
public abstract override void CreateCustomColumns()
{
Grid.AddColumn("Client" ...
Grid.AddColumn("ClientLocation" ...
Grid.AddColumn("ClientPhoto" ...
}
}
--> "Abstract method cannot declare a body"
So, how can I override CreateCustomColumns() in ClientComponentController, but still force it to be overridden again in derived classes like ClientInvoicesComponentController?
Of course it still CAN be overridden anyway, but there is nothing to indicate to the developer that it MUST be overridden... which is my aim.
-Brendan
In a word: Not.
A method being abstract means that it is declared but not defined. Being defined but abstract does not really make sense in this context, so it is not possible.
I would also very much like to know your use case. If there is some behaviour you want subclasses to inherit, but also add their own functionality, you could so something like this:
public abstract class BaseClass
{
public void DoSomething()
{
// Base class behaviour goes here.
DoSomethingInternal();
}
protected abstract void DoSomethingInternal();
}
public class SubClass : BaseClass
{
protected override void DoSomethingInternal()
{
// Sub class behaviour goes here.
}
}
In this case, I think it would be better to divide your logic into 2 methods, one method you play with and the other method your users play with. Assuming the "CreateCustomColumns" method is the name you want your users to override, you create another method, say "CreateCustomColumnsCore", for yourself. The classes may look like this:
public abstract class ComponentController
{
protected abstract void CreateCustomColumnsCore();
}
public abstract class ClientComponentController : ComponentController
{
protected override void CreateCustomColumnsCore()
{
// your code here
CreateCustomColumns(); // call users' implementation
}
public abstract void CreateCustomColumns();
}
public class ClientInvoicesComponentController: ClientComponentController
{
public override void CreateCustomColumns()
{
// user must implement this method.
}
}
Users can still override your CreateCustomColumnsCore method, this could be a feature or a bug based on if you can permit users to do this.

How to override parameter defined in interface method with richer type?

I have these:
public class TennisPlayer
{
}
public class RogerFederer : TennisPlayer
{
}
public class RafaelNadal : TennisPlayer
{
}
And then I have some classes with methods, like these:
public abstract class Manager
{
protected abstract void ScheduleFriendlies(TennisPlayer player);
}
public class RafaelNadalManager : Manager
{
public void ScheduleFriendlies(RafaelNadal rn)
{
//throw new NotClayException();
}
}
public class RogerFedererManager : Manager
{
public void ScheduleFriendlies(RogerFederer rf)
{
//throw new NotGrassException();
}
}
//'RafaelNadalManager' does not implement inherited abstract member 'Manager.ScheduleFriendlies(TennisPlayer)'
The thing I'm trying to achieve is that I would want to have child classes of Manager but every such class will be tied to one player and hence the methods in those child classes (Manager classes) will be specific to that player. In other words Roger should have his own ScheduleFriendlies while Rafael should have his own.
How do I go about this? Alternate designs would do, but keep in mind:
What I can alter: The inheritances, its routes etc
But do not have the luxury to: Take off child manager classes and merge into one (in other words, I need RogerFederer and RogerFedererManager as separate classes).
I tried this:
public abstract class Manager
{
protected abstract bool ScheduleFriendlies<T>(T player) where T : TennisPlayer;
}
public class RafaelNadalManager : Manager
{
protected override bool ScheduleFriendlies<T>(T player)
{
//but how do I enforce the caller that only RafaelNadal object can be
//passed to this but not RogerFederer?
}
}
You were close, but you need the class generic, not just the method:
public abstract class Manager<T> where T : TennisPlayer
{
protected abstract bool ScheduleFriendlies(T player);
}
You could then use:
public class RafaelNadalManager : Manager<RafaelNadal>
{
protected override bool ScheduleFriendlies(RafaelNadal player)
{}
}

Require child classes to call super.doSomething() if overrides it?

I have a abstract class named Vehicle:
public abstract class Vehicle {
public void run() {
addToRunningVehicleList();
}
}
I want that every classes that extends Vehicle must call super.run() if they override run method. For example:
public class Car {
#Override
public void run() { // Error here because does not call super.run()
carRunningAnimation();
}
}
Is it possible in OOP concept, or Java/C#?
EDIT: Following Petar Ivanov, I have this code:
public abstract class Vehicle {
public final void run() {
Log.e("Run", "Add To List");
runImp();
}
public void runImp() {}
}
public class Car extends Vehicle {
#Override
public void runImp() {
Log.e("Run", "Run in Car");
}
}
However, it's not very good for public APIs. When extending Vehicle, the end-users must override runImp, but then they have to call run() method, so I have to make public both run and runImp, which make nothing better.
Here is how I would do it (C#):
public abstract class Vehicle {
public void Run() {
//code that will always run
addToRunningVehicleList();
//code that can be overriden
RunImpl();
}
protected virtual void RunImpl() { }
}
public class Car : Vehicle {
protected override void RunImpl() {
carRunningAnimation();
}
}
You can make the RunImpl protected to make sure it can't be called outside the subclasses of Vehicle.
If you need to require certain code to run in addition to the child class' implementation, perhaps you need to split this into multiple methods:
(C# example)
public abstract class Vehicle
{
public void Run()
{
// Code that always runs before...
RunCore();
// Code that always runs after...
}
protected virtual void RunCore()
{
}
}
Remember who you are designing for. If it's an internal piece of code a comment will suffice. If it's a public API and you want people to inherit then you need to write a piece of documentation telling them to do it.
In C# you can do some sneaky stuff with virtual and non-virtual methods but in Java as all inheritence is virtual it's a lot harder to enforce this without using an abstract base class.
Using an ABT may limit your ability to provide further inheritence and force modification of other code.

Categories