web-dev-qa-db-ja.com

プロパティの概念を含めるためにOOPはどのように進化しましたか

私はC++の出身で、現在の仕事ではすべてC#を使用していますが、パブリックフィールドとプロパティの違い、およびこのバリエーションと化身のすべての違いについて、多くのQ&Aを読んでいます基本的な質問(たとえば、これはSO投稿および関連するすべてのリンク questions )です。これらの質問はすべて、プロパティシステムですが、最初にプロパティをサポートすることを決定したすべての言語の設計者が何を考えていたかという観点からこの主題にアプローチするのは良いことだと思います(Wikipediaの記事のリストをチェックしてください here =)。どうやってOOP C++/Javaから進化して、Wikipediaの記事がメソッドとメンバーデータの中間点として興味深いものに拡張したかを説明します。

「つまり、プロパティはクラスのメンバーコード(メソッド)とメンバーデータ(インスタンス変数)の中間にあり、プロパティはパブリックフィールドよりも高いレベルのカプセル化を提供します。」

[〜#〜] msdn [〜#〜] はさらに背景を追加します:

「プロパティは技術的にはメソッドと非常に似ていますが、使用シナリオの点でかなり異なります。これらはスマートフィールドと見なされます。フィールドの呼び出し構文とメソッドの柔軟性があります。」

この中間レベルのカプセル化がプログラミング全般に役立つことが証明された方法を知りたいのですが。この概念は、OOPパラダイムを表現したプログラミング言語の最初の具体化には存在しなかったと想定しています。

12
jxramos

それはすべてカプセル化と統一アクセス原則についてです。

オブジェクトは、既存のデータを返すか、メソッドを実行してメッセージに応答できる必要がありますが、送信者はどちらがどれであるかを認識できません。または、送信者側からこれを表示する場合:送信者は、既存のデータにアクセスするか、統一されたインターフェイスを介してメソッドを実行できる必要があります。

これを実現するには、いくつかの方法があります。

  • データを完全に削除し、メソッドを用意する(Newspeakがこれを行う)

    • 上記のより過激な形式:データを取り除くパブリックインターフェース内、つまりデータを常にプライベートにし、パブリックインターフェース内でメソッドのみを公開(Smalltalk、Ruby =これを行う)
  • メソッドを完全に削除し、データのみを取得します(これは自分で行います。「メソッド」はインスタンス変数に割り当てられたMethodオブジェクトです。インスタンス変数は仮想ディスパッチで検索されます)

  • メソッドとデータを構文的または意味的に区別しません(Scalaはこれを行います。フィールドへのアクセスは、引数リストなしのメソッドの呼び出し(foo.bar)と構文的に区別できません。フィールドへの割り当ては、特別な名前のメソッド(foo.bar = baz)の呼び出しと構文的に区別できません。 foo.bar_=(baz)と同じです。つまり、foo_=という名前のメソッドを呼び出します。読み取り専用の値は、スーパークラスのパラメーターリストなしのメソッド(つまり、val foo)でオーバーライドまたは実装できます(またはabstractval be implement)サブクラスでメソッドdef fooを使用して)

ただし、JavaはUniform Access Principleに準拠していません。 Javaでは、データへのアクセスとメソッドの実行を区別できます。 foo.barfoo.bar()とは異なります。この理由は、フィールドとメソッドは意味的および構文的に異なるためです。

C#は、言語にプロパティを追加することでこれを修正しようとします。基本的にはフィールドのように見えるメソッドです。ただし、メソッド呼び出しは、フィールドやプロパティへのアクセスとは異なるルックアンドフィールを備えています。現在、フィールドとプロパティにはUniform Accessがありますが、メソッドにはまだありません。

したがって、これで実際に問題が解決するわけではありません。物事にアクセスする3つ目の方法を追加して、物事にアクセスする2つの異なる方法を持つことは修正できません。その3番目の方法が他の2つの方法の1つに似ていても、(少なくとも)2つの方法があります。 1つを除いてすべての異なる方法を取り除くか、違いを取り除くことによってのみ修正できます。

メソッド、プロパティ、フィールドを備えた言語を使用するのはまったく問題ありませんが、3つすべてに統一されたアクセス権が必要です。

5
Jörg W Mittag

ええと、100%確かではありませんが、おそらくあなたが思っているよりも簡単なことでしょう。 OO 90年代のモデリングスクールから、カプセル化されたメンバー属性を使用してクラスをモデリングする必要がありました。C++やJavaなどの言語で実装すると、これは通常、多くのゲッターとセッターなので、比較的単純な要件のための多くの「ノイズ」コードです。リンクされたWikipediaの記事にリストされている言語のほとんど(おそらくすべてはこれをチェックしていません)は、オブジェクトの「プロパティ」を90年代以降。

言語設計者がそのノイズを減らすために構文上の砂糖を追加することを決めた主な理由だったと思います。そして、プロパティは確かに「コアOOコンセプト」ではありませんが、少なくともオブジェクト指向に関係するsomethingを持っています。「OOPの進化」(質問のタイトルが想定しているように)、ただし、実装を容易にするために、プログラミング言語レベルでOO modelingをサポートしています。

18
Doc Brown

あなたはそれを後方に持っています(ちょっと)。 Lambda Calculus は、プログラミング言語の中核となる正式な基盤として存在し、何十年も前から存在しています。 フィールドはありません。

変更可能な状態をモデル化するには、2つの抽象化を行う必要があります。 1つはいくつかの状態を設定することを表し、もう1つはその状態を取得します(私のバージョンの TaPL の第13章を参照)。聞き覚えがある? 理論的の背景から、OOは進化してこのようなものはありませんでした。OOプログラミング言語101を読み、ベビーステップを作りました転送します。

実践的の観点から、2つのかなり明確な動機があります。あなたはC++のバックグラウンドを持っているので、パブリックフィールドがある場合に何が必要になるでしょう。たとえば、テキストボックス内のテキストです。デザインを変更して「このテキストボックスが変更されるたびに何とかする」ようにしたい場合はどうなりますか?開発者が自分で「UpdateTextbox」を呼び出すのを信頼できないため、そのフィールドを削除し、関数を1つまたは2つ作成して、そのロジックを結び付けます。これは、veryAPIに対する重大な変更です(残念ながら、.NETのプロパティの実装における重大な変更です)。この種の動作は、Windows APIでは場所全体です。これはMicrosoftにとって大きな問題であるため、C#はおそらくそれをそれほど痛くないものにしたいと考えていました。

他の大きな動機は Java Beans とその親族です。 Javaリフレクションを使用してGetXSetXのペアを検索し、それらを最新のプロパティのように効果的に扱うために、多くのフレームワークが構築されました。しかし、それらは実際の言語構成では、これらのフレームワークは壊れやすく、扱いにくいものでした。名前を入力すると、物事は静かに壊れてしまいます。リファクタリングされた場合、プロパティの反対側を移動するものは何もありません。field/ get/setボイラープレートのすべてを行います(Javaの場合でも!)C#は主に「教訓を学んだJava」として開発されたので、その種の苦痛はそれらの教訓の1つでした。

しかし、最大のものは、プロパティのコンセプトが成功していることです。理解しやすく、使い方も簡単です。これらは採用を大いに助け、そしてtoolとして、プログラマーはプロパティが問題のサブセットをどちらの関数よりもきれいに解決することを発見しましたまたはフィールド。

11
Telastyn

具体的には、.netでは、プロパティは古いVisual Basicの時代に由来しますが、今日の私たちの考え方では、オブジェクト指向ではありませんでした。それは主に当時の新しいCOMシステムを中心に構築されたもので、必ずしもすべてを表面として扱うのではなく、コードだけでなくグラフィックエディターでもアクセスできるプロパティを公開するコンポーネントの観点からすべてをクラスとして扱いました。 VBおよび新しく作成されたC#が.netにマージされたとき、VBはOOP機能の多くを獲得し、それらを削除すると次のようになるため、プロパティを保持しました一歩後退-Visual Studioにあった自動コード更新ツールがすべてのプロパティをゲッターとセッターに置き換えていて、すべてのCOMライブラリとの互換性が失われていたとしましょう。すべての.net-languagesでそれらをサポートするのは論理的ですそのため、相互運用性の問題や内部実装を公開することなく、コンポーネントをフレームワーク全体で使用できます。

3
niwax

プロパティは構文糖子にすぎないため、プロパティはオブジェクト指向プログラミングとは何の関係もありません。プロパティは表面的にはフィールドのように見えます。netの世界では、いくつかの点でフィールドのように動作することをお勧めしますが、どのような意味でもフィールドではありません。プロパティは、1つまたは2つのメソッドの構文糖衣です。1つは値を取得するためのメソッドで、もう1つは値を設定するためのメソッドです。 setメソッドまたはgetメソッドのいずれかを省略できますが、両方を省略できません。 getメソッドによって返された値を格納するフィールドがない場合があります。フィールドと構文を共有し、フィールドを頻繁に使用するため、プロパティをフィールドに関連付けます。

プロパティはフィールドよりも優れています:

  • プロパティセットメソッドでは、プロパティ値が格納される前に、新しい値、またはオブジェクトの状態が、一連の前提条件または不変条件に対してチェックされる場合があります。
  • プロパティ値の取得が論理的にフィールド値の取得と同等であると考えることができる場合、プロパティgetメソッドが便宜上存在することがあります。
  • プロパティセットメソッドは、親オブジェクトへの通知やプロパティ値への変更のリスニングオブジェクトなど、他の操作を実行する場合があります。

プロパティはフィールドの抽象化であり、構文上の便宜上、C#などの言語はプロパティにフィールド構文を採用しています。

3
Frank Hileman

実装含意の問題です。プロパティはOOPまたはJavaがシーンにヒットしました(Simuulaではエッジに粗さがあり、そこにあり、Smalltalkの基本です)プロパティを持つエンティティは概念的にコードが添付された値とは異なります。一部の言語規則のgetおよびsetプレフィックスは、水を濁らせるためにのみ機能します。これらは、フィールドとプロパティの違いを認識させます。これらのフィールドは、言語に対して慣用的な方法でget/setせずに直接アクセスされる可能性があります。

OOPの全体的なポイントは、物事を「実際の」世界のエンティティであるかのように扱うことであり、いくつかのコードが混在する構造体としてだけではありません。別のプログラマは、私が物事を実装した方法について、そしてそれらが取得および/または設定することが許可されているさまざまな値のどれが実数であり、どれが仮想であるかについてまったく気にする必要はありません。私のベクトルに出くわした場合、ベクトルオブジェクトの内部に角度と大きさまたは実数部と虚数部を格納するかどうかを知る必要があります。ライブラリのV2.0で表現を変更しても、コードにまったく影響しないはずです(ただし、クールな新機能を活用してください。同様に、エンティティがエンティティの外部のデータに依存する可能性のあるプロパティがありますが、それは疑いなく字句の観点からはプロパティです。データを知っているとしても、私にあなたの年齢を明らかにする計算を実行してくださいその「オブジェクト」で利用できるのは、生年月日(プライベートの不変のメンバー)と今日の日付(タイムゾーン、夏時間、および国際日付変更線に依存するパブリックの自動増分環境プロパティ)です。年齢はメソッドではなくプロパティですが、到達するためにはある程度の計算が必要であり、(人工的に制限された寿命を持つもののおもちゃのコンピュータ表現を除いて)フィールドとして格納することはできません。

プロパティをフィールドやメソッドの粗悪な子として考えるのではなく、特殊な種類のプロパティとしてのメソッドのこと、つまりエンティティが実際にできることではなく、エンティティが実行できることのほうがはるかに満足です。それ以外の場合は、概念的にオブジェクトやエンティティを扱っているのではなく、たまたまコードが付加されているデータコレクションを扱っています。 implementaionsは同じである可能性がありますが、-含意は異なります。

ただし、この抽象化にはコストがかかることは言うまでもありません。クラスを使用するプログラマーが、データが格納されているときにデータにアクセスしているか、計算が必要な値を取得または設定しているかを判断できない場合、言語も必ずしも不確実なレベルがあります(したがって、すべてがアクセサ/セレクタと値の間を仲介するコードを必要とすることを要求します)。 「コード付き構造体」には概念的に何も問題はありません-それらは確かにはるかに効率的です-しかし、それらは至る所に実装をリークし、それはOOP 。

2
Stan Rogers

絶対に何もない。プロパティとOOPは互いに何の関係もありません。プロパティは関数呼び出しの構文糖にすぎないため、関数呼び出しが行うOOP添付とまったく同じです。つまり、なし。

ちなみに、ウィキペディアは完全に正しくありません。 Java=にあるgetMember/setMemberパターンは、C#のプロパティとまったく同じ利点(および欠点)を提供します。必要に応じて、Cでもこのパターンを複製できます。

C#のプロパティは、言語でサポートされている構文糖にすぎません。

0
DeadMG