【问题标题】:Exposing methods of a class only to a Manager class?仅将类的方法公开给 Manager 类?
【发布时间】:2019-07-25 19:17:45
【问题描述】:

假设我有一个 Screen 类。这个类几乎没有受保护的抽象方法,如 EnterScreen、ExitScreen。

我只想通过 ScreenManager 类更改屏幕,但我不能,因为这两种方法都受保护。

如果我公开方法,我可以在 ScreenManager 中调用这两个方法,然后我将它们公开给接受 Screen 类作为参数的其他类,因此它们可以轻松调用 Enter 和 Exit Screen。

您知道如何仅通过 ScreenManager 进行调用而不将这两种方法都暴露给其他类吗? (只有 ScreenManager 可以换屏)

提前致谢。

编辑:@derHugo 提供了一个答案,我应该使用命名空间和 internal 关键字,但是,我已经尝试过了,但它没有按预期工作(内部类的方法仍然可以在不同的命名空间中访问作为 Screen 类)。我将在下面提供代码和我得到的行为。

namespace Test
{
    public abstract class Screen<T> 
    {    
        internal abstract void EnterScreen();

        internal abstract void ExitScreen();
    }
}

// 单独的类

namespace Test
{    
    public class SimpleScreen : Screen<UnityEngine.GameObject>
    {
        internal override void EnterScreen() { }

        internal override void ExitScreen() { }
    }
}

// 这没有命名空间,但我仍然可以访问 Screen 类的内部方法。

public class GameManager : MonoBehaviour, IInitializable<SimpleScreen>
{
    public void Initialize(SimpleScreen screen)
    {
        //   I CAN REFERENCE .Enter & ExitScreen methods here 
    }    
}

【问题讨论】:

  • 我的立场是正确的,但我认为这是你能得到的最接近的,除非你使用嵌套的私有类。即使方法是private,您仍然可以使用Reflection 访问它们
  • internal 关键字是基于程序集而不是命名空间的访问修饰符。在 Unity 中,所有脚本都编译成两个程序集:编辑器目录中的所有内容,然后是其他所有内容。如果要使用 internal 关键字,则需要在 Unity 之外编写该 C#,将其编译为 DLL,然后将该 DLL 放入您的项目中。
  • @rootpanthera 你找到了对你有用的这个问题的答案吗?

标签: c# unity3d


【解决方案1】:

一种解决方法是将您的 screenManager 实例注入您的 Screen 并将这些Actions 传递给它,它有权访问:

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);
}

【讨论】:

    【解决方案2】:

    需要使某些公共方法仅可用于某些其他类可能表明类关系中的设计缺陷。也许将部分职责转移到ScreenManager 本身可以解决这个问题。

    当您声明 Screenabstract 时,您打算使用可以被覆盖的公共或受保护方法。因此,您对其他类隐藏它们的唯一选择是使它们受到保护。

    访问受保护成员的唯一方法是从类本身,派生或嵌套类型。

    您可以将ScreenManger 类嵌套在您的Screen 中,它将默认为私有或公开。如果我正确理解了您的问题,我举了一个例子,但没有 Unity。

    希望对你有帮助

    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.
        }
    }
    
    

    【讨论】:

      猜你喜欢
      • 2020-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-12
      • 2019-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多