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


11

私はC ++のバックグラウンドから来て、現在の仕事でC#を使い果たしており、パブリックフィールドとプロパティの違いと、このバリエーションと化身の前後の違いについて多くのQ&Aを読んでいます。基本的な質問(たとえば、このSO投稿と関連するすべてのリンクされた質問)。これらの質問はすべて、プロパティシステムの存在を当然とする実際的な違いの観点から説明されていますが、最初のプロパティをサポートすることを決めたすべての言語のデザイナーがこのテーマにアプローチするのは良いと思います場所は考えていました(Wikipediaの記事のリストをチェックしてください)。OOPはC ++ / Javaからどのように進化し、Wikipediaの記事で興味深いことにメソッドとメンバーデータの中間であると特定されました。

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

MSDNはさらに背景を追加します。

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

カプセル化のこの中間レベルが一般的なプログラミングに有用であることが判明したことを知りたいと思います。この概念は、OOPパラダイムを表現したプログラミング言語の最初の化身には存在しなかったと思います。


8
むき出しの言語機能は、ゲッターメソッドとセッターメソッドに便利な構文糖衣です。解釈と用語の背後にさらに深い理由があるかどうかはわかりません。

OOエキスパートのラウンドでは、あなたの質問のタイトルは刺激的であり、あなたが本当に求めていたものから気を散らす可能性があります。私はオブジェクト指向の専門家であると自負しているわけではなく、私は数年間「オブジェクト指向ユーザー」です。
Doc Brown 14

Pythonの「パラメーターのないメソッド」からC ++に移行するのを見逃すようになったのは、構文上の利点です。IMO BMI = bob.weight/sq(bob.height)なしで読みやすくなり()ます。
OJFord 14

Active X(COM)オブジェクトを構成する方法として、プロパティは元の(.netではない)Visual Basicにあったと思います。このツールのプロパティグリッドは、おそらく言語でのプロパティの採用と関係があります。元のVisual Basicは多くの点でオブジェクト指向ではありませんでしたが、クラスのようなものを作成する機能がありました。
フランクヒルマン14

継続:プロパティウィンドウは、コードを記述せずにオブジェクトを構成する方法でした。RAD開発と呼ばれていました。このリンクは、VB6のプロパティウィンドウのスクリーンショットが含まれていますmicrosoft.com/mspress/books/WW/sampchap/4068.aspx
フランクHileman

回答:


5

カプセル化と統一アクセスの原則がすべてです。

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

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

  • データを完全に取り除き、メソッドのみを持ちます(Newspeakがこれを行います)

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

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

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

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

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

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


1
なぜあなたは(そして他の人も)Uniform Accessの維持がとても重要だと思うのですか?メソッドを使用して、パラメータを指定して、その動作や動作を変更できます。この機能を持たないフィールドまたはプロパティを使用すると、通常はデータを返すだけです(ただし、プロパティはプライベートフィールドを公開する代わりにメソッドを実行するように実装できます)。私は慣れているからかもしれませんが、均一なアクセスを強制することで、優雅さや生産性を向上させることはできますか?実装の詳細をクラス外に漏らしているのではないかと心配していますか?
マイクはモニカをサポートします14

1
UAPは、パブリックインターフェイスを壊さずに実装の詳細を変更する自由を確保することです。通常の例は、ロギングの追加です。メソッドを介してアクセスを提供する場合、メソッドの内部を簡単に変更してログに書き込むことができます。パブリックフィールドでは、最初にすべてのクライアントコードを壊すメソッドに変換しないとロギングを追加できません。重大な変更が危険にさらされない場合、メソッドの使用は必須です。プロパティは完全なメソッドですが、フィールドのように見えるため、最適な妥協点です。UAPに準拠すると、カプセル化が向上し、密結合が減少します。
アモン14

この質問に対する良い答えはたくさんありますが、これはプログラミング言語の性質のより基本的な側面を引き出し、関連するUAPの正式な概念について詳しく説明することで頭を悩ませたと思います。固体
jxramos 14

18

まあ、私は100%確信していませんが、物事はおそらくあなたが期待するよりも簡単だと思います。90年代のOOモデリングスクールからは、カプセル化されたメンバー属性を持つクラスをモデリングする必要がありました。C++やJavaなどの言語で実装されると、多くのゲッターとセッターを含むコードになります。比較的単純な要件のコード。リンクされたウィキペディアの記事にリストされている言語のほとんど(おそらくすべて、これをチェックしなかった)は、90年代以降にオブジェクトの「プロパティ」を導入し始めたことに注意してください。

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


プロパティはフィールドの抽象化であり、フィールドはオブジェクト指向プログラミングの一部であるという意味を除いて、オブジェクト指向プログラミングとは関係ありません。ただし、オブジェクト指向プログラミングではプロパティは必要ありません。正しく説明します。
フランクヒルマン14

2
@FrankHilemanは:「プロパティは、フィールドの抽象化され、そしてフィールドは、オブジェクト指向プログラミングの一部である」 -まあ、あなたのような私には音がコンセプトが一致していることがあり、実際に、少なくとも何か OOPを行うには。そしてそれはあなたが私を落胆させた理由ですか?
ドックブラウン14

3
笑。彼を責めることはできますか?彼はトイレをすり抜け、頭を洗面台にぶつけました。とにかく...私がいつも見た方法は、プロパティ厳密にはオブジェクト指向のものではないということでした。これらはカプセル化に役立ち、カプセル化はオブジェクト指向に役立ちます。
MetaFight 14

1
ハ!これは私にとって、programmers.stackexchangeの入門書です。Lol、プレーンol stackoverflowでの同等の経験よりもはるかに熱くなりました。
jxramos 14


11

あなたはそれを逆方向に持っています(種類)。Lambda Calculusは、プログラミング言語の中核となる正式な基盤として存在し、数十年にわたって存在しています。フィールドはありません。

可変状態をモデル化するには、2つの抽象化を行う必要があります。1つは何らかの状態を設定することを表し、もう1つはその状態を取得します(参照用に私のバージョンのTaPLの第13章)。おなじみの音?理論的な背景から、OOはこのようなものを持つように進化しませんでした。オブジェクト指向はプログラミング言語101を読み、一歩前進した。

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

もう1つの大きな動機は、Java Beanとその親族です。Javaリフレクションを使用して、それらを最新のプロパティのように検索GetXおよびSetXペアリングし、効果的に扱うために、多くのフレームワークが構築されました。しかし、これらは実際の言語構造ではないため、これらのフレームワークは脆弱で扱いにくいものでした。名前の入力を間違えた場合、物事は黙って中断されます。一方がリファクタリングされた場合、プロパティの反対側に移動するものはありません。そして、field / get / set定型文のすべてを行うのは冗長で退屈でした(Javaの場合でも!)。C#の大部分は「教訓を備えたJava」として開発されたため、この種の痛みはその教訓の1つでした。

しかし、最大のことは、プロパティの概念が成功していることです。わかりやすく、使いやすいです。これらは導入に大いに役立ち、ツールとして、プログラマーはプロパティが問題のサブセットを関数やフィールドよりもきれいに解決することを発見しました。


7
関係のない正式ながらくたへの参照が多すぎるため、私は主にあなたを落胆させました。プログラミング言語の実際の実装には、そのモデルがラムダ計算に含まれているかどうかよりもはるかに深刻な考慮事項があります。
DeadMG 14

9
@DeadMG-それは確かに真実ですが、一方で、プログラミング言語の実装者は、その無関係な形式的ながらくたに常に精通しているでしょう。彼らのデザインに影響を与えなかったと考えるのは単純です。
テラスティン14

3
これは間違いなく「無関係な正式ながらくた」ではありません。ただし、ラムダ計算は初期のプログラミング言語ではあまり考慮されていなかったかもしれません。もしそうなら、CPUはおそらくその考え方に向いているでしょう。
フランクヒルマン14

3
@FrankHileman -私はLispは...それを考えられてかなり確信している
Telastyn

4
@Telastyn-はい-Lispはもともとプログラミング言語であるはずではなかった、覚えていますか?
フランクヒルマン14

3

特に.netでは、プロパティは古いVisual Basicの時代に由来しますが、今日のようにオブジェクト指向ではありませんでした。それは、すべてを必ずしもクラスとしてではなく、コードとグラフィカルエディタの両方でアクセスできるプロパティを公開するコンポーネントの観点から表面的に処理した当時の新しいCOMシステムを中心に構築されました。VBと新しく作成されたC#が.netにマージされたとき、VBは多くのOOP機能を取得し、それらを削除することは後戻りのようなものであるため、プロパティを保持していました-Visual Studioにあった自動コード更新ツールがすべてのプロパティをゲッターとセッターに置き換え、すべてのCOMライブラリとの互換性を壊していました。すべてをサポートすることは論理的なことでしょう。


Delphiから来たC#の祖先、それ以前のObject PascalとTurbo Pascal with Objectsを無視すべきではないと思います。これらはオブジェクト指向であり、プロパティがありました(OPにTP5.5のプロパティがあるか、追加されたかは覚えていませんが、実用的には良いアイデアだったため、AndersによってC#に継続されたと思われます。)
amaca

あなたがたまたまこの質問のコンポーネントの側面にぶつかったのはたまたまだったことです。C#が満たすいくつかのproperty-method-eventモデルの一部としてプロパティをリストしたサイトにリンクしている質問にコメントを追加しました。その後、質問のページで「コンポーネント」を検索して、いくつかの誤検出を見つけましたが、あなたの答えは実際にリンクしたものと重複しています。
jxramos

3

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

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

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

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


2
ウィキペディアの記事の最初の行。「一部のオブジェクト指向プログラミング言語のプロパティは、特別な種類のクラスメンバーです...」したがって、最初の文は明らかに間違っています。そして、残りの部分は質問に答えません。
Doc Brown 14

1
@DocBrown:興味深い応答。多くのウィキペディアの記事は明らかに間違っています。この特定の記事の著者を擁護していると思いますか?
フランクヒルマン14

1
オブジェクト指向プログラミング言語のすべての機能がオブジェクト指向の概念に関連しているわけではありません。
フランクヒルマン14

1
それはあなたが質問に答えていないという事実を変えません。
ドックブラウン14

3
オプションのセッターだけではないことに注意してください。プロパティのみを設定できます。
テラスティン14

2

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

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

プロパティをフィールドやメソッドの卑劣な子と考えるのではなく、メソッドを特殊なプロパティとして考えることよりもはるかに満足します。つまり、エンティティが本来のことではなく、できることです。そうでなければ、概念的にオブジェクト/エンティティを扱っているのではなく、たまたまコードがアタッチされているデータコレクションを扱っています。implementaionsは同一であってもよいが、意味が異なっています。

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


私はいくつかの点に同意し、他の人に反対するが、全体的メッセージは良いものです:オブジェクトに関するいくつかの情報を計算する必要がありますが、技術的にはまだ情報であるということができ、アクションより行わ
ファラプ14

0

絶対に何もありません。プロパティとOOPは互いに関係ありません。プロパティは、関数呼び出しの構文上のシュガーに過ぎず、したがって、関数呼び出しが行うのとまったく同じOOP添付を持ちます。つまり、なしです。

ところで、ウィキペディアは完全に間違っています。Javaで表示されるgetMember / setMemberパターンには、C#のプロパティとまったく同じ利点(および欠点)があります。必要に応じて、Cでもこのパターンを複製できます。

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


3
クラスまたはオブジェクトコンテキスト以外のプログラミング言語でプロパティの概念を見たことがありますか?していません。
ドックブラウン

1
@DocBrown:実装しました。事実、プロパティは、通常の関数呼び出しに対する改善が低いため、言語作成者にとって非常に価値の低いターゲットです。
DeadMG 14

1
OPは、一般的なプログラミング言語の概念として、プロパティの歴史について尋ねていました。そして実際には、歴史的な意味で、プロパティとOOPの間には関係があります。
ドックブラウン14

2
おそらく、このプロパティの概念をOOPパラダイム自体に帰するのはちょっとしたかもしれませんが、コンセプトとしては確かに個々の言語とその機能を超越しています。たぶん、2つの間の適切なオントロジーを明確にするのに苦労しています。質問のタイトルを通じて、プロパティがOOPの基本的な機能/概念であり、OOP形式を作成または破壊することを示唆しているわけではありませんが、このOOP空間には現実だけがあると思うので、質問をそのように表現しました。
jxramos 14

4
これらはC#の単なる構文シュガーではなく、アセンブリメタデータ内に個別のメンバーとして存在し、データバインドなど、フィールドではできないプロパティを使用して処理を行うことができます。
アンディ14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.