0

In my Unity C# project I have these interfaces:

interface IGameService
{
 void Initialize(params object[] args);
}

interface IADManager : IGameService
{
 void Show();
}

interface IIAPManager : IGameService
{
 void Purchase();
}

And a class:

public class MonatizationManager : IAPManager, IADManager
{
 ... 
}

I have a list of IGameService classes, that I need to initialize (also i'm using Zenject). For example:

// this basicly means that _iapSettingsProvider and _adSettingsProvider will contain link to a class that implements IADManager and IIAPManager interfaces. In my case this is the same class for these two  interfaces - MonatizationManager 
[Inject] private readonly ISomeSettingsProvider1 _someSettingsProvider1; // example
...
[Inject] private readonly IADManager _iapSettingsProvider;
[Inject] private readonly IIAPManager _adSettingsProvider;
...
[Inject] private readonly ISomeSettingsProvider2 _someSettingsProvider2; // example

// here i initialize my classes (some are managers, some are just providing game settings etc)
// all initQueue's elements must implement IGameService interface
var initQueue = new GameTaskQueue();
initQueue.Add(new GameTaskInitService(_someSettingsProvider1)); // example
...
initQueue.Add(new GameTaskInitService(_iapSettingsProvider));
initQueue.Add(new GameTaskInitService(_adSettingsProvider));
...
initQueue.Add(new GameTaskInitService(_someSettingsProvider2)); // example

// here my queue is starting to initialize my IGameService classes (basically just calling Initialize() method for each element in the queue)
initQueue.Start();

Here comes the problem: I have same class (MonatizationManager) for IADManager and IIAPManager while i also need to Initialize these interfaces separately. So, how do MonatizationManager class would look like?

First, i tried:

// it did not work
public class MonatizationManager : IAPManager, IADManager
{
 IGameService.IADManager.Initialize(params object[] args) {...}
 IGameService.IIAPManager.Initialize(params object[] args) {...}
}

Then i tried (didn't work either):

interface IADManager : IGameService
{
 new void Initialize(params object[] args);
 void Show();
}

interface IIAPManager : IGameService
{
 new void Initialize(params object[] args);
 void Purchase();
}

public class MonatizationManager : IAPManager, IADManager
{
 void IIAPManager.Initialize(params object[] args)
 {
  ...
 }

 void IADManager.Initialize(params object[] args)
 {
  ...
 }
// compiler wants me to also write this method, but i think i don't need it
 public void Initialize(params object[] args)
 {
  ...
 }
}

Is it possible to somehow explicitly implement Initialize(params object[] args) method for these two interfaces (IIAPManager and IADManager) in my MonatizationManager class?

  • I don't understand your manager-class in the first example. Either yur manager **is** of type `IIAdManager`, or it **has** one. Both makes no sense IMHO. In the first case it should *implement* that interface, in the second one it should just *use* it by calling any of its members. Apart from this you cannot call any function outside of a member. – MakePeaceGreatAgain Mar 28 '22 at 07:20
  • @MakePeaceGreatAgain, thank you for your comment. I didn't realy get your point. My MonatizationManager implements two interfaces, it does not has them, as you put it out, and therefore MonatizationManager is responsible for these two functionalities in my project (ads and in app purchases). I guess, i just missunderstood you, could you please clerify your point. – Albert Dzhurakulov Mar 28 '22 at 08:43
  • 1
    Why would it matter? Why do you need to differ between the two interfaces? If this service needs to be initialized it shouldn't matter for which of the two interfaces right? It should simply do all required initialization for either one of the interfaces it implements ... Otherwise you should probably just split it up into two managers ... – derHugo Mar 28 '22 at 09:18
  • You're right, i ended up with same decision (to use one Initialize method for both functionalities). In fact, there were two managers (because Android plutform 3-d party packages allowed it, we picked one for iap and one for ads), but now i need to launch my project on webGL too and i found single 3-rd party package wich is providing all the staff. – Albert Dzhurakulov Mar 28 '22 at 12:04

1 Answers1

2

Your design is a bit overcomplicated. There's only a single Intialize-method you should implement, not two. It would be pretty confusing for a client to use your class and having to need to call Initialize twice. However that single implementation can of course do whatever you want, for example call two private methods

Furthermore your manager-class already is an IADManager, so there's no reason to also have a member of that type and use that one by calling its members (unless you implement the decorator-pattern or similar).

So I'd suggest to use this instead:

interface IGameService
{
    void Initialize(params object[] args);
}    
interface IADManager : IGameService
{
    void Show();
}    
interface IIAPManager : IGameService
{
    void Purchase();
}

public class MonatizationManager : IAPManager, IADManager
{
    void Initialize(params object[] args) 
    {
        // code for initializing the one interface
        // code for initializing the other interface
    }
    void Show() { ... }
    void Purchase() { ... }
}

As an aside you usuially initialize specific classes, not an interface. Although every class has some initialize-method doesn't neccessarily mean such initialization should be available on the public interface. Having such a design would enable multiple calls to Initialize for instance, which is usually not intended. Instead you should provide a fully usable class within the constructor-code (unless there's some heavy magic happening, in which case you would implement some lazy-loading). Then your client-code does not need to know if or if not it already initialized the class, as it already gets a fully initialized one.

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111
  • Thank you for your answer and architectural suggestions for my project. This may work, if i'd called MonatizationManager.Initilize explicitly in my code, however I'm not doing it. To Initialize all my managers i use ```GameTaskQueue``` and ```GameTaskInitService```, these classes use IGameService interface (therefore casting any manager to IGameService) to call it's Initialize() method. And i'm looking for a way to use a single class ```MonatizationManager``` to be initialized twice for it's ```IAPManager``` and ```IADManager``` interfaces. Dunno if it's even possible. Hope you understand me. – Albert Dzhurakulov Mar 28 '22 at 08:53
  • @AlbertDzhurakulov the fact that you need two kinds of initialization does not mean you need to implement the interface twice, nor does it mean a client need to call two functions. Instead there's a single initialization-function that internally calls two (maybe private) methods. A client would expect to call initialize **once** and only once. The fact that this call will internally initialize two different things is completely irrelevant to the client. – MakePeaceGreatAgain Mar 28 '22 at 09:06
  • Okay, i guess, i got your point, thank you! I ended up using just one Initialize() call for both ad and iap functionalities, it's clearer and simpler for understanding. – Albert Dzhurakulov Mar 28 '22 at 11:54