81

インターフェイスで保護されたアクセスメンバーを宣言することに反対する議論は何ですか?たとえば、これは無効です。

public interface IOrange
{
    public OrangePeel Peel { get; }
    protected OrangePips Seeds { get; }
}

この例では、インターフェースは、実装者が少なくとも継承者にインスタンスを提供するIOrangeことを保証します。実装者が望む場合は、スコープを完全に拡張できます。OrangePipspublic

public class NavelOrange : IOrange
{
    public OrangePeel Peel { get { return new OrangePeel(); } }
    protected OrangePips Seeds { get { return null; } }
}

public class ValenciaOrange : IOrange
{
    public OrangePeel Peel { get { return new OrangePeel(); } }
    public OrangePips Seeds { get { return new OrangePips(6); } }
}

インターフェイスのメンバーの目的は、継承者(サブクラス)にprotectedサポートコントラクトを提供することです。次に例を示します。

public class SpecialNavelOrange : NavelOrange
{
    ...
    // Having a seed value is useful to me.
    OrangePips seeds = this.Seeds; 
    ...
}

(確かに、これはsでは機能しませんstruct

インターフェイスのprivateまたは修飾子のケースの多くはわかりませんが、と修飾子の両方をサポートすることは完全に合理的であるように思われます。internalpublicprotected


メンバーをsから完全に分離することにより、sのprotectedメンバーの有用性を説明してみます。interfaceinterface

継承者のコントラクトを適用するための新しいC#キーワード、を想像してみましょうsupport。これにより、次のように宣言できます。

public support IOrangeSupport
{
    OrangePips Seeds { get; }
}

これにより、クラスを契約して、保護されたメンバーを継承者に提供できます。

public class NavelOrange : IOrange, IOrangeSupport
{
    public OrangePeel Peel { get { return new OrangePeel(); } }
    protected OrangePips Seeds { get { return null; } }
}

protectedクラスは、そもそもメンバーを提供することによってこの契約をすでに暗示しているため、これは特に有用ではありません。

しかし、これを行うこともできます:

public interface IOrange : IOrangeSupport
{
   ...
}

IOrangeSupportこれにより、実装するすべてのクラスに適用しIOrange、特定のメンバーを提供するように要求しprotectedます。これは、現在私たちができることではありません。

4

15 に答える 15

63

誰もが、実装の詳細がなく、パブリックメンバーのみを持つインターフェイスの要点を打ち明けたと思います。あなたが探しているのは抽象クラスです。

public interface IOrange
{
    OrangePeel Peel { get; }
}

public abstract class OrangeBase : IOrange
{
    protected OrangeBase() {}
    protected abstract OrangePips Seeds { get; }
    public abstract OrangePeel Peel { get; }
}

public class NavelOrange : OrangeBase
{
    public override OrangePeel Peel { get { return new OrangePeel(); } }
    protected override OrangePips Seeds { get { return null; } }
}

public class ValenciaOrange : OrangeBase
{
    public override OrangePeel Peel { get { return new OrangePeel(); } }
    protected override OrangePips Seeds { get { return new OrangePips(6); } }
}

編集:クラスOrnamentから派生したPlasticOrangeがある場合、IOrangeのみを実装でき、Seeds保護メソッドは実装できないと主張するのは公正です。それは結構です。定義上、インターフェースは、クラスとそのサブクラスの間ではなく、呼び出し元とオブジェクトの間のコントラクトです。抽象クラスは、私たちがこの概念に到達するのと同じくらい近いです。そして、それは問題ありません。あなたが本質的に提案しているのは、ビルドを壊すことなくサブクラスをある基本クラスから別の基本クラスに切り替えることができる言語の別の構成です。私には、これは意味がありません。

クラスのサブクラスを作成する場合、サブクラスは基本クラスの特殊化です。基本クラスの保護されたメンバーを完全に認識している必要があります。ただし、突然基本クラスを切り替えたい場合は、サブクラスが他のIOrangeで機能する必要があることは意味がありません。

公正な質問があると思いますが、それはコーナーケースのようであり、正直なところ、それによるメリットは見当たらないと思います。

于 2009-02-05T15:13:07.083 に答える
16

意味がないからです。インターフェイスは公開されたコントラクトです。私は IThing であるため、求められれば IThing メソッドを実行します。IThing に、教えられない方法を実行することを確認するように依頼することはできません。

于 2009-02-05T14:40:24.217 に答える
10

インターフェイスは、具体的な実装が何であるかを知らなくても、人々がクラスにアクセスできるようにするために存在します。これは、実装をデータ受け渡し契約から完全に切り離します。

したがって、インターフェイス内のすべてがパブリックである必要があります。非パブリック メンバーは、実装にアクセスできる場合にのみ役立ちます。したがって、インターフェイス定義に意味のある貢献をすることはありません。

于 2009-02-05T14:40:20.737 に答える
7

インターフェイス メンバーパブリック API です。protectedetc は実装の詳細であり、インターフェイスには実装がありません。あなたが探しているのは明示的なインターフェースの実装だと思います:

public class NavelOrange : IOrange
{
    public OrangePeel Peel { get { return new OrangePeel(); } }
    OrangePips IOrange.Seeds { get { return null; } }
}
于 2009-02-05T14:40:08.507 に答える
1

抽象基本クラスとは対照的に、保護されたインターフェイスは(抽象クラ​​スの)「複数の継承」を許可します。これは、1回か2回有用であることがわかりました...

于 2019-10-12T23:24:28.647 に答える
1

記録のために: C# 8.0 の時点で、インターフェースに含めることができるようになりました

  • 保護されたメンバー
  • プライベートメンバー
  • 実装

要するに、以前は複数の基本メンバーの実装を共有するなど、複数の継承をサポートする言語でしか利用できなかったいくつかの機能を紹介します。

https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/default-interface-methods-versions https://jeremybytes.blogspot.com/2019/11/c-8-interfaces -public-private-and.html

于 2021-09-11T11:10:37.160 に答える
0

.net インターフェイスを実装するクラスには、すべてのインターフェイス メンバーの実装を含める必要があります。さらに、任意のクラスは、必要なメンバーを派生クラスに公開できます。インターフェイスの実装に、派生クラスからのみ使用できるメンバーを含める必要があることを要求することは、(1) そのようなメンバーがインターフェイスの外部の何かから見える可能性があるか、(2) インターフェイス実装が使用できる場合を除いて、有用な目的にはなりません彼ら自身が定義していないメンバー。protectedインターフェイスにネストされたクラス (インターフェイスのメンバーにアクセスできる) を含めることが許可されている場合、protectedインターフェイスメンバーは理にかなっています。実際、インターフェイス内にネストされたクラスがそのインターフェイスの拡張メソッドを定義できる場合、これらは非常に便利です。残念ながら、そのような施設はありません。

ところで、インターフェイスにクラスを入れ子にすることができなくても、internalインターフェイス メンバーにアクセス修飾子を適用すると、インターフェイスが定義されているアセンブリだけがその実装を定義できるという効果が得られます。

于 2012-06-12T19:03:38.157 に答える
0

インターフェイスは、特定のオブジェクトができることに関するすべてであるため、そのインターフェイスを実装するクラスを使用する場合、開発者はすべてのメンバーが実装されることを期待するため、保護されたアクセス修飾子はインターフェイスに対して何の意味もありません。

于 2009-02-05T14:39:52.890 に答える
0

インターフェイスには、パブリック メンバーのみが含まれます。保護されているとは、宣言しているものはすべて、クラスおよび派生クラスのインスタンスでのみ使用できることを意味します。

于 2009-02-05T14:40:16.367 に答える