実際、C# は、特別な言葉を使わずに純粋な OOP の方法で同じ動作を取得する可能性を提供します。これはプライベート インターフェイスです。
質問に関しては、友人に相当するC#は何ですか? この記事と重複しているとマークされており、誰も本当に良い実現を提案していません - ここで両方の質問に対する答えを示します。
ここからの主なアイデアは次のとおりです。プライベートインターフェイスとは何ですか?
たとえば、別のクラスのインスタンスを管理し、それらに対していくつかの特別なメソッドを呼び出すことができるクラスが必要です。このメソッドを他のクラスに呼び出す可能性を与えたくありません。これは、c++ の世界で友人の c++ キーワードが行うこととまったく同じです。
実際の良い例は、一部のコントローラーが現在の状態オブジェクトを更新し、必要に応じて別の状態オブジェクトに切り替えるフル ステート マシン パターンであると思います。
あなたは出来る:
- Update() メソッドを public にする最も簡単で最悪の方法 - なぜそれが悪いのか、誰もが理解してくれることを願っています。
- 次の方法は、内部としてマークすることです。クラスを別のアセンブリに配置すれば十分ですが、その場合でも、そのアセンブリ内の各クラスは各内部メソッドを呼び出すことができます。
- プライベート/保護されたインターフェイスを使用します-そして、私はこの方法に従いました。
Controller.cs
public class Controller
{
private interface IState
{
void Update();
}
public class StateBase : IState
{
void IState.Update() { }
}
public Controller()
{
//it's only way call Update is to cast obj to IState
IState obj = new StateBase();
obj.Update();
}
}
Program.cs
class Program
{
static void Main(string[] args)
{
//it's impossible to write Controller.IState p = new Controller.StateBase();
//Controller.IState is hidden
var p = new Controller.StateBase();
//p.Update(); //is not accessible
}
}
では、継承はどうでしょうか。
明示的なインターフェイス メンバーの実装は仮想として宣言できないため、で説明されている手法を使用する必要があり、IState を保護されているものとしてマークして、コントローラーからも派生できるようにする必要があります。
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()");
}
}
最後に、クラス Controller のスロー継承をテストする方法の例:
ControllerTest.cs
class ControllerTest: Controller
{
public ControllerTest()
{
IState testObj = new PlayerIdleState();
testObj.Update();
}
}
すべてのケースをカバーし、私の答えが役に立ちました。