「プライベート」インターフェースの使用例?


8

インターフェイスがクラスのパブリックプロパティと関数を定義する方法と同様の方法で、クラスの特定の内部プロパティと関数を適切に定義できる有効なユースケースがあるかどうか疑問に思いました。

人間を説明するクラスを構築する必要があるタスクを想像してみてください。

明らかに、各人間はヒューマノイドクリーチャーですが、すべてのヒューマノイドクリーチャーが人間であるとは限らないため、おそらく次のような機能を持つインターフェースIHumanoidがあります(ボディプランをクラスにハードコードすることは役に立たないため)。

public interface IHumanoid {
    function get head():IHead;
    function get torso():ITorso;
    function get leftArm():IArm;
    function get rightArm():IArm;
    function get leftLeg():ILeg;
    function get rightLeg():ILeg;
}

さらに、そして明らかに、各人間は哺乳動物ですが、すべての哺乳動物が人間であるとは限らないため、どこかに浮かぶ男性と女性の2つの定義を持つ別のインターフェイスIMammalがおそらくあります。

public interface IMammal {
    function procreate(partner:IMammal):void;
}

public interface IMaleMammal extends IMammal {
    function inseminate(female:IFemaleMammal):void;
}

public interface IFemaleMammal extends IMammal {
    function conceive(partner:IMaleMammal):Boolean;
    function giveBirth():IMammal;
    function nurse(offspring:IMammal):void;
}

したがって、クラスはおそらく次のようになります。

public class Human implements IHumanoid, IMammal {
    private var _head:IHead;
    private var _torso:ITorso;
    private var _leftArm:IArm;
    private var _rightArm:IArm;
    private var _leftLeg:ILeg;
    private var _rightLeg:ILeg;

    public function Human() {
        // ctor...
    }

    public function get head():IHead {
        return _head;
    }

    public function get torso():ITorso {
        return _torso;
    }

    public function get leftArm():IArm {
        return _leftArm;
    }

    public function get rightArm():IArm {
        return _rightArm;
    }

    public function get leftLeg():ILeg {
        return _leftLeg;
    }

    public function get rightLeg():ILeg {
        return _rightLeg;
    }

    public function procreate(partner:IMammal):void {
        // "abstract" function
    }
}

public class MaleHuman extends Human implements IMaleMammal {
    override public function procreate(partner:IMammal):void {
        if (partner is IFemaleMammal) {
            inseminate(partner);
        }
    }

    public function inseminate(female:IFemaleMammal):void {
        female.conceive(this);
    }
}

public class FemaleHuman extends Human implements IFemaleMammal {
    override public function procreate(partner:IMammal):void {
        if (partner is IMaleMammal) {
            conceive(partner);
        }
    }

    public function conceive(partner:IMaleMammal):Boolean {
        // ...
    }

    public function giveBirth():IMammal {
        // ...
    }

    public function nurse(offspring:IMammal):void {
        // ...
    }
}

これにより、クラスをさらに実装することができ、既存のインターフェースを使用して他のクラスを実装するタスクを取得するまで、すべてが正常に機能します。おそらくゴリラ、シャチ、カモノハシ。

カモノハシが現在のインターフェース構造(*咳*卵を産む哺乳類*咳*)にもたらす大きな問題を無視すると、ゴリラ2脳、シャチ8肺、カモノハシ半分を与えることを妨げるものがない「問題」があります。 1ダースの肝臓。また、哺乳類の構造を理解するのに十分な規律があるかもしれませんが、他の開発者がAPIを開いても、外の世界では問題ないように真剣にねじ込まれたものをコーディングする場合は、同じことを保証できません。

したがって、非公開の関数とプロパティを定義する「プライベートインターフェイス」のようなものを作成するための有効なユースケースがあるかどうか疑問に思いました。おそらくこれらの線に沿った何か:

public structure SMammal {
    function get brain():IBrain;
    function get liver():ILiver;
    function get leftLung():ILung;
    function get rightLung():ILung;
    function get leftKidney():IKidney;
    function get rightKidney():IKidney;
}

public class Human implements IHumanoid, IMammal follows SMammal {
    private function get brain():IBrain {
        // ...
    }

    private function get liver():ILiver {
        // ...
    }

    // etc. etc.
}

このような機能はプログラミング言語に存在しますか?抽象クラスを使用してこれを解決できますか?それとも、パブリックインターフェイスが何らかの形で期待どおりに機能している限り、これを気にする必要はありませんか?


インタフェースを表すの「IMumle」の方法は、私の意見では、悪い習慣です

2つのコメント。まず、言語インターフェースの詳細ではなく、XMLスキーマに基づいて全体の議論を行うことができるようです。第二に、「検証」は「常に」というわけではありませんが、「構造」から最もよく分離されています。
rwong 2012

回答:


3

また、哺乳類の構造を理解するのに十分な規律があるかもしれませんが、他の開発者がAPIを開いても、外の世界では問題ないように真剣にねじ込まれたものをコーディングする場合は、同じことを保証できません。

彼らにあなたの構造に従うことを強制することによって正確に何を得るのですか?あなたはおそらくいくつかの高度な使用法を壊します、おそらく複数の脳を持つ動物の場合があります。そして、クライアントプログラマーは、馬を納屋に留めようとしてウィンドウを閉じようとするような、クレイジーな方法でクラスの実装を混乱させる可能性があります。

クライアントプログラマーを囚人のように扱わないでください。それらがパブリックインターフェイスに従っている場合は、コードを実行します。


私は囚人のようにAPIを使用するものを扱いたくありませんが、既存のフレームワークへのプラグインなどの構造化方法に関するガイドラインを提供することについて考えていました。プラグインインターフェースは、拡張機能がフレームワークでどのように使用されるかを通知するだけですが、プラグインが内部でどのように動作するかについては何も通知しません。

いくつかのcookie-cutterアプローチではカバーされていない高度な使用法について要点がありますが、パブリックインターフェースでも簡単に実行できます(たとえば、C#IList<T>では、返す必要がある/したいが、インターフェイスが返すように要求するAN IEnumerable<T>)。そして最後に重要なことですが、複数の(私たちの複製された臓器すべてのように冗長な)脳を持つ既知の動物は存在しません。したがって、このようなもの(スパイダーなど)の場合があるかもしれませんが、それはほぼ確実に哺乳類ではないので、とにかく完全に異なるインターフェース/構造になります。

@arotter、私はすべて、内部で物事を構造化するための最良の方法に関するガイドラインを提供してくれています。しかし、特定の内部構造を必要とする理由は何もありません。インターフェイスの重要なポイントは、実装ではなくパブリックインターフェイスを定義することです。
Winston Ewert 2012

1

インターフェイスタイプはデフォルトでパブリックメンバーであるため、その中のすべてがパブリックでなければなりませんが、これを確認しました。

/programming/792908/what-is-a-private-interface

msdnから:

インターフェイスは、メソッド、プロパティ、イベント、インデクサー、またはこれら4つのメンバータイプの任意の組み合わせで構成されます。インターフェイスには、定数、フィールド、演算子、インスタンスコンストラクタ、デストラクタ、または型を含めることはできません。静的メンバーを含めることはできません。インターフェースのメンバーは自動的に公開され、アクセス修飾子を含めることはできません。

http://msdn.microsoft.com/en-us/library/ms173156.aspx


はい、インターフェースのメンバーは公開されています。それはあなたがあなた自身のインターフェースで公開しないいくつかのインターフェースタイプのプライベートメンバーを持つことができないことを意味しません。インターフェイスの実装はパブリックです。インターフェイスの使用は、好きなだけプライベートにすることができます。OPは基本的に、特定のインターフェイスをプライベートに使用するためにクラスを宣言する方法を尋ねているため、実装するクラスがこれらのメソッドを実際に実装することが保証されます。
Marjan Venema 2012

はい、私はあなたに同意します。そのため、プライベートメンバーとのインターフェースを示すリンクを投稿したのはなぜですか。
Ali Jafer 2012

あ、そう。よく隠されています... :)
Marjan Venema

問題は、C#(または他の既存の言語)のインターフェイスではなく、基本的な概念に関するものでした。この投稿はそれをまったく扱っていません。
Peter Taylor

0

このような機能はプログラミング言語に存在しますか?抽象クラスを使用してこれを解決できますか?それとも、パブリックインターフェイスが何らかの形で期待どおりに機能している限り、これを気にする必要はありませんか?

それは確かにあります。一部の言語には、ほとんどすべての機能が存在します。

たとえば、Objective-C ++(iOS / Macプログラミング)では、クラスが少なくとも2つのインターフェイスを持つことが標準的な手順です。その上に公開されており、私的なものです。場合によっては、他の場所で定義されている追加のインターフェイスもあることがあります(たとえば、低レベルの文字列クラスには、文字列を定義するものとは完全に別のフレームワーク/ライブラリで定義されている文字列に対してGUI画面描画操作を実行するためのインターフェイスがありますクラス)。

基本的に私がパブリック/プライベートを扱う方法は簡単です:

パブリックインターフェイス要素は変更できません。コードをリファクタリングまたは改善しても、パブリックインターフェイスは以前とまったく同じように動作する必要があります

一方、プライベートインターフェイスは、いつでも変更または完全に削除できます。新しい動作を理解するためにクラスのすべてのコードを更新する限り、問題ありません。多くの場合、パブリックインターフェイスは、実際の作業をプライベートインターフェイスに引き渡す1つまたは2つのラインメソッドでいっぱいになります。

Objective-C ++には、インターフェイスで「保護されている」という概念もあります。この場合、サブクラスでは何かを利用できますが、外部クラスでは利用できません。

通常、私のコードはパブリックとプライベートの間で約半分に分割されています。たまに重宝しますが、プロテクトはあまり使いません。


0

少なくとも.NET言語では、アクセス指定子をインターフェースに適用することが可能です。これは、アセンブリの内部クラスのいくつかの組み合わせが共通の機能を共有しているが、それらの組み合わせと機能が階層関係に適合しない場合に役立ちます。機能が階層関係に適合しないという事実は、それらを表すためにインターフェースを使用することを必要とするが、外部コードがインターフェースを実装すると主張する型を定義することを許可されるべきであることを決して意味しない。さらに、インターフェイスには、パラメーター型または戻り値の型がインターフェイス自体よりも狭いアクセス権を持つメソッドを含めることはできません。クラスFredが宣言されinternal、インターフェースにIFredを返すメソッドがあるFred場合、インターフェースを宣言する必要ありますinternal。入れ子になったクラスがいる場合Fred.Joeであるprivateと、ネストされたインタフェースがFred.IJoe返すメソッドを持ってFred.Joe、その後、Fred.IJoe同様に宣言する必要がありますprivate

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.