事实上,C# 提供了一种纯 OOP 的方式来实现相同的行为,而不需要特殊的关键词——私有接口。
由于问题 “C# 中 friend 的等价物是什么?” 被标记为重复,并且那里没有人提出真正好的实现方法,所以我将在这里回答这两个问题。
主要思想取自于这里:“什么是私有接口?”
假设我们需要一个类来管理另一个类的实例并调用它们的某些特殊方法。我们不想让任何其他类调用这些方法。这正是在 C++ 世界中 friend 关键字所起的作用。
我认为在实际应用中,一个很好的例子就是完整状态机模式,其中某个控制器更新当前状态对象,并在必要时切换到另一个状态对象。
您可以:
- 最简单也是最糟糕的让Update()方法公开的方式-希望每个人都明白为什么这样做很糟糕。
- 下一种方式是将其标记为内部的。如果您将类放到另一个程序集中,那么这已经足够好了,但即使在该程序集中的每个类都可以调用每个内部方法。
- 使用私有/受保护接口-我采用了这种方式。
Controller.cs
public class Controller
{
private interface IState
{
void Update();
}
public class StateBase : IState
{
void IState.Update() { }
}
public Controller()
{
IState obj = new StateBase();
obj.Update();
}
}
Program.cs
class Program
{
static void Main(string[] args)
{
var p = new Controller.StateBase();
}
}
好的,那继承呢?
我们需要使用由于显式接口成员实现不能声明为虚拟的技术描述中所述的技术,并将IState标记为受保护的,以便从Controller进行派生。
Controller.cs
public class Controller
{
protected interface IState
{
void Update();
}
public class StateBase : IState
{
void IState.Update() { OnUpdate(); }
protected virtual void OnUpdate()
{
Console.WriteLine("StateBase.OnUpdate()");
}
}
public Controller()
{
IState obj = new PlayerIdleState();
obj.Update();
}
}
PlayerIdleState.cs
public class PlayerIdleState: Controller.StateBase
{
protected override void OnUpdate()
{
base.OnUpdate();
Console.WriteLine("PlayerIdleState.OnUpdate()");
}
}
最后,举个例子来测试通过继承的方式控制器类:
ControllerTest.cs
class ControllerTest: Controller
{
public ControllerTest()
{
IState testObj = new PlayerIdleState();
testObj.Update();
}
}
希望我涵盖了所有情况,我的回答有用。