none
interfaceの実装をsealedしたい RRS feed

  • 質問

  • インターフェイスを継承したabstractクラスを作り、それを継承して実装クラスを作ろうと考えています。

    [コード例]

    Code Snippet

     

            //インターフェイス
            interface ITest
            {
                int Method();
            }
            //抽象
            abstract class  BaseClass : ITest
            {
                public int Method()
                {
                    //何かの処理をする
                    return this.MethodImpl();
                }
                protected abstract int MethodImpl();
            }
            //実装
            class Impliment : BaseClass
            {
                protected override int MethodImpl()
                {
                    return 0;
                }
            }

     

     

    実装クラスではインターフェイスのメソッドを直接実装させたくありません。

    [禁止したい例]

    Code Snippet
            //実装
            class Impliment : BaseClass
            {
               //直接実装されると困る!
               public int Method()
               {
                  return 10;
               }

                protected override int MethodImpl()
                {
                    return 0;
                }
            }

    試しに抽象クラスでインターフェイスメソッドをsealedで宣言してみましたが、コンパイルエラーになります。

    どのように実現したらよいでしょうか?

    2009年1月26日 12:22

回答

  • 抽象クラスでインターフェイスの明示的実装を行えばいいでしょう。インターフェイスを経由しない限りは private メンバ扱いになります。

     

    ところで、Implement クラスで ITest を再実装することができる、という点は考慮しておくべきです。

    インスタンスを BaseClass として扱う分には問題ないでしょうが、ITest として扱うと挙動が変わってきます。

    2009年1月26日 12:49

すべての返信

  • 抽象クラスでインターフェイスの明示的実装を行えばいいでしょう。インターフェイスを経由しない限りは private メンバ扱いになります。

     

    ところで、Implement クラスで ITest を再実装することができる、という点は考慮しておくべきです。

    インスタンスを BaseClass として扱う分には問題ないでしょうが、ITest として扱うと挙動が変わってきます。

    2009年1月26日 12:49
  • インターフェイスの明示的実装で希望の動作はできそうです。

    ただ、インターフェイスの明示的実装を行ったところ次のコードがビルドエラーになります。

    Code Snippet

     

            //インターフェイス
            interface ITest
            {
                int Method();
                int Method2();
            }
            //抽象
            abstract class  BaseClass : ITest
            {
                protected abstract int MethodImpl();
                int ITest.Method()
                {
                    this.Method2(); //エラー CS1061 'BaseClass' に 'Method2' の定義が含まれておらず、型 'BaseClass' の最初の引数を受け付ける拡張メソッドが見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足しています。
                    return this.MethodImpl();
                }
                int ITest.Method2()
                {
                    return 2;
                }
            }

     

     

    ということで明示的実装をしたメソッドではthisをインターフェイスにキャストして使うことにしました。

    少々キャストが気に入らないのですが当面は問題なさそうです。

     

    Code Snippet
            //抽象
            abstract class  BaseClass : ITest
            {
                protected abstract int MethodImpl();
                int ITest.Method()
                {
                    ((ITest)this).Method2();
                    return this.MethodImpl();
                }
                int ITest.Method2()
                {
                    return 2;
                }
            }

     

     

     

    2009年1月27日 11:23