2017-10-11 13 views
0

これは重複していませんが、私はGoogleまたはSO検索で見つけることはできません。メソッドのオーバーライドされたメソッドの実装のアクセシビリティをprotectedにする場合は、abstractまたはprotected virtualのいずれかを作成する唯一のオプションはありますか?私はインターフェイスが宣言を指定するが、アクセシビリティ/スコープをクラスの実装に任せていることを知っているが、私は確信したい。子実装のためのメソッドの制限範囲

メソッドの範囲を制限する唯一の方法がabstract \ protected virtualを介して「これはクラスの実装または子のオーバーライドの実装に適用されます」というセマンティクスを与えることです。

説明するコードサンプル。私は次のことを行うことができ、そのような実装の範囲を制限することができます。私は子供の実装のみoverrideOnlyMeorChildrenCanDoAction()protectedとしてではなく、publicことを保証する上で行うことにより

public class BaseClass 
{ 
    protected virtual void OnlyMeOrChildrenCanDoAction() 
    { 
     // leave empty as current class is structural/conceptual 
     // but child instances may need it 
    } 
} 

abstractまたはprotected virtualに頼らずにprotectedに限定する別の方法がありますか?このようなメソッドを作成する例は、hereのようにObject.Finalize()です。

または、質問を多少逆にするには、実装に範囲が限定されていないことを確認しない限り、protected virtualというメソッドを作成するのはなぜですか?それとも同じことをする別の方法がありますか?

+1

私はあなたが何を求めようとしているかを理解するのが非常に苦労しています。いくつかのコード例を追加することをお勧めします。私はまだdownvoterではなかった – maccettura

+0

私はまだかなり失われています。 – maccettura

+0

@maccettura 'protected virtual'メソッドを作成した場合は、そのメソッドを子実装でのみ' protected'として使用できることを保証します。子の実装を 'public'としてオーバーライドすることはできません。これを行う唯一の方法は上記のアプローチですか? – DiskJunky

答えて

3

virtualの意味と使い方を誤解していると思います。 は、仮想クラスが宣言されている場合、親クラスのメソッドをオーバーライドできます。子クラスのoverrideメソッドは、親クラスのメソッドと同じ可視性を持たなければなりません。

インターフェイスで宣言されたメソッドの実装は、常にpublicです。

abstractメソッドを宣言すると、virtualという宣言と同じ効果がありますが、クラスに実装しておらず、クラスから派生した具体的なクラスで実装する必要があります。

+0

インターフェイスの実装の範囲は実装者に任されており、実装者が宣言しない限り(私が知っている限り) 'public'ではありません。しかしこれは私の質問には答えません。子供の実装の範囲を制限する別の方法がありますか? – DiskJunky

+1

"インターフェイスメンバーを実装するには、実装クラスの対応するメンバーがパブリックで、静的でなく、インターフェイスメンバーと同じ名前とシグネチャを持つ必要があります。 https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/ –

+0

私は訂正しました。これは、インターフェイスが行く方法ではないと答えています – DiskJunky

2

技術的には、コンパイラは、親からオーバーライドするときにメソッドのアクセス修飾子を変更することを許可しないので、その質問に対する答えは、クラス内でメソッドを宣言することによって、派生クラスで利用可能(抽象的であるかどうかは別個の懸念事項であり、アクセスレベルには関係しない)。

ただし、派生クラスは、保護されたメソッドをパブリックメソッドから呼び出すなど、他の方法で関数を公開することは自由であり、その防止方法はありません。

"なぜ"あなたが保護された抽象メンバを持つかについては、Template Methodパターンの多くの実装で大きな例が見られます。アルゴリズムの構造を記述する抽象基本クラスを持ち、各ステップの境界内で何が起きるかの具体的なステップを派生クラスに任せることができます。この場合、実装する1つの方法は、基本クラスを抽象クラスとして宣言し、パブリックメソッドをアルゴリズムの「エントリポイント」として使用し、アルゴリズム内で使用される特定のメソッドを保護された抽象メソッドとして定義して、派生クラスの責任は、このパターンは、世界が消費しようとしているものだけを公開するという素晴らしい仕事をしますが、時にはヘルパーメソッドの可視性を保護から内部に上げることによって対処される単体テストの観点からいくつかの課題を提示する可能性があります。

+0

私の質問は、 'protected' /' public'の周りではなく、子クラスに機能を実装する方法を与えることでした。つまり、「公的/保護された」という混乱は、私の質問の悪い言い分、それに謝罪に至るまで、より深刻なものです。あなたのポイントは良いものであり、私が走っていたものではないと言われています。 – DiskJunky

1

派生クラスがOnlyMeOrChildrenCanDoActionのパブリックバージョンを実装しないようにするために、C#言語を使用することはできません。 protected virtualとマークしても、派生クラスはnewキーワードを使用してメソッドをカバーし、アクセシビリティを変更できます。たとえば、次のように

public class BaseClass 
{ 
    protected virtual void OnlyMeOrChildrenCanDoAction() 
    { 
     // leave empty as current class is structural/conceptual 
     // but child instances may need it 
    } 
} 

public class DerivedClass : BaseClass 
{ 
    public new void OnlyMeOrChildrenCanDoAction() 
    { 
     Console.WriteLine("This is public."); 
    } 
} 

public class Program 
{ 
    public static void Main() 
    { 
     var b = new BaseClass(); 
     //b.OnlyMeOrChildrenCanDoAction(); //Will not compile 

     var d = new DerivedClass(); 
     d.OnlyMeOrChildrenCanDoAction(); //Look! It's public! 
    } 
} 

出力:DotNetFiddleで利用可能

This is public. 

コード。

発信者がOnlyMeOrChildrenCanDoActionにコールするのを防ぐには、発信者がインターフェイスのみを使用することをお勧めします。 OnlyMeOrChildrenCanDoActionがインターフェイスにない場合、派生クラスがパブリッククラスメンバーとして公開することを決定したとしても、呼び出し元が呼び出す方法はありません。とにかくこれは良いSOLIDデザインです。

一方、自分の開発チームが悪いことを心配しているので、発信者があまり心配していない場合は、FxCopなどのソースコードルールエンジンを組み込むことをお勧めしますあなたの継続的なビルドプロセス。開発者はまだこのメソッドを追加することができますが、そうした場合にビルドに失敗するようにルールを設定することができます。

+0

質問はアクセスを制限しようとするのではなく(あなたの答えは徹底していますが)、抽象的なメカニズムを介して機能を実装するオプションを子供の実装に与える別の方法があったとします'または 'protected virtual'のいずれかです。これまでの回答に基づいて、それは「いいえ」です。私はその質問が難解である理由を感謝しますが、それはなぜ「Finalize」がそのまま実装されたかを中心にしています。 – DiskJunky

関連する問題