なぜプライベート変数が必要なのですか?


210

クラスにプライベート変数が必要なのはなぜですか?

私が読んだプログラミングに関するすべての本は、これはプライベート変数であると述べています。

これらの説明の言葉遣いは、私たちが本当に自分の職業に信頼の危機を抱えているように思えました。他のプログラマがコードを台無しにしようとしているように、説明は常に聞こえました。しかし、プライベート変数を持たない多くのプログラミング言語があります。

  1. プライベート変数は何を防ぎますか?

  2. 特定のプロパティをプライベートにするかどうかをどのように決定しますか?デフォルトですべてのフィールドがプライベートである必要がある場合、クラスにパブリックデータメンバーがあるのはなぜですか?

  3. どのような状況で変数を公開する必要がありますか?


9
質問は言語にとらわれないように聞こえますが、javaとc ++とタグ付けされています。これらの2つの言語以外からの視点に興味があるなら、おそらくそう言うべきでしょう。
ジェームズ

8
記録として、プライベートメソッドを作成しても「セキュリティ」は向上しません。アプリケーションの他の部分は、リフレクションを使用してプライベートメンバーにアクセスできます。
kba

3
プライベート変数とパブリック変数の使用法と違い、およびそれらが存在する理由は、一般的なオブジェクト指向の原則のコンテキストでのみ理解できます。個別に理解することはできません。あなたはおそらくその観点からそれを見る必要があります。
ナザールメルザ


3
車でシートベルトを使用している人を捕まえた場合は、運転免許証を持ち去る必要があります。明らかに、彼らは自分の運転能力を信用していないからです。
gnasher729

回答:


307

それはそれほど信頼の問題ではなく、管理の複雑さの問題です。

パブリックメンバーは、クラスの外部からアクセスできます。これは、実用的な考慮事項では「潜在的にどこでも」を意味します。パブリックフィールドで何か問題が発生した場合、犯人はどこにいてもかまいません。そのため、バグを追跡するには、かなり多くのコードを調べる必要があります。

対照的に、プライベートメンバーは同じクラス内からしかアクセスできないため、何か問題が発生した場合、通常はソースファイルを1つしか確認できません。プロジェクトに100万行のコードがあり、クラスが小さく保たれている場合、バグ追跡の労力を1000分の1に減らすことができます。

別の利点は、「結合」の概念に関連しています。別のクラスによって使用されるmクラスのパブリックメンバーは、依存関係を導入します。in を変更する場合は、inの使用法も確認する必要があります。さらに悪いことに、クラスで何が使用されているかを教えてくれないので、コードベース全体を検索する必要があります。それがあなたが書いているライブラリである場合、あなたは外部のコードを確認する必要さえあるABmAmBAm変更によってプロジェクトが中断することはありません。実際には、ライブラリは元のメソッドシグネチャを可能な限り長く維持する傾向がありますが、それがどれほど苦痛であっても、メジャーバージョンの更新によって重大な変更のブロックが導入されます。対照的に、プライベートメンバーを使用すると、依存関係をすぐに除外できます。外部からはアクセスできないため、すべての依存関係はクラス内に含まれます。

この文脈では、「他のプログラマー」にはあなたの未来と過去の自分が含まれます。変数Yを使ってこのXを行うべきではないことを知っいるかもしれませんが、顧客が何らかの機能の実装を緊急に必要とする場合、3か月後には忘れてしまいます。あいまいな方法でY。

ですから、いつプライベートにするかについては、デフォルトですべてをプライベートにし、絶対にパブリックにする必要がある部分だけを公開します。プライベートにできるほど、より良いものになります。


24
問題の核心である+1。ただし、頻繁に使用される変数がプライベートに保たれるようにするために、フープを通過するのをやめたとき、個人的にコードの保守が容易であることがわかりました。将来エラーが発生する可能性はありますが、ふるいにかけるコード行は60行少なく、起動する変数と関数は少なくなります;)
ジェフリースウィーニー

48
現代のコンピューティングの聖杯は、複雑さを抑えています。

1
デバッグの一部は、単に「何がうまくいかなかったか」に直接駆り立てるのではなく、「何がうまくいかなかったのか」を把握し、残っているものに私の調査を集中するというラウンドアバウトのプロセスをとることです。コンパイラーにプライベート変数などのツールで「発生した可能性のあるもの」を定義してもらうことができれば、時間を節約できます。うまくいかなかったことが起こらないことを証明するまれな場合にのみ、おそらく個人データを上書きするバッファオーバーランのような、より恐ろしい仮定を掘り下げる必要があります。
コートアンモン

2
まさにそれ。人々は「情報隠蔽」を聞くと、彼らは暗号化キー、データベースの資格情報などのようなもののためにプライベート変数を使用する必要があることだと思う
ウェイン・ヴェルナー

2
@AdamZernerは、最初にゲッター/セッターを持つことについて「教えないでください」(martinfowler.com/bliki/TellDontAsk.html)を参照してください-しかし、そうでなければ、値の内部表現をいつでも自由に変更できるためですあなたが望む。いつものように、例外...(例のDTO)がある
doubleYou

111

プライベート変数は、コードの特定の部分に依存することを防ぐのに役立ちます。たとえば、何らかのデータ構造を実装するとします。データ構造のユーザーは、実装方法を気にせずに、明確に定義されたインターフェイスを介して実装を使用するだけで済みます。理由は、実装に誰も依存していない場合、いつでも変更できるためです。たとえば、バックエンドの実装を変更してパフォーマンスを改善できます。実装に依存していた他の開発者は壊れますが、インターフェイスユーザーは問題ありません。クラスのユーザーに影響を与えずに実装を変更できる柔軟性があることは、プライベート変数(より広くはカプセル化)を使用することで得られる大きな利点です。

また、それは実際には「信頼の危機」ではありません。データの一部を公開すると、誰もそれに依存していないことを保証できません。特に期限が迫っている中で、パブリックインターフェイスを経由する代わりに、実装固有の変数に依存することは非常に便利です。さらに、開発者は、変化する可能性のあるものに依存していることを常に認識しているわけではありません。

したがって、この種の質問が他の質問に答えてくれることを願っています。実装の詳細はすべてプライベートにする必要があり、パブリック部分は、クラスを使用するための小さく、簡潔で、明確に定義されたインターフェイスにする必要があります。


24
IMOは、libの作成者とlibの消費者との間のコミュニケーションも重要です。パブリックインターフェイスは「これを使用」に似ており、プライベートは「それを使用しない」に似ていますが、Javaでは、プライベートにすると安全で明確になるため、誤って使用することできません。
チャクリット

5
@chakritその他:プライベートフィールドとメソッド実際に使用する人は、(リフレクションを介して)使用できることに注意してください。private「主にセキュリティを目的としたもの」ではなく、「セキュリティ」を提供するものではありません。これは、コンパイラにアクセスしないという強力なヒントに過ぎません。

@delnanは、「偶然」というフレーズに注意してください。
チャクリット

@chakritはい、あなたが間違っていたことを意味するつもりはありませんでした。その点を宣伝したかっただけです。

1
@delnan:一部の言語では、プライベートフィールドは特定の形式のセキュリティを提供します。たとえば、アクセスレベルと修飾子(プライベート、封印など)がC#のセキュリティ目的に役立つかどうかに対するEric Lippertの回答を参照してください。
ブライアン

25

ここのキーワードはEncapsulationです。OOPでは、オブジェクト/クラスを適切にカプセル化するためにプライベート変数を使用します。

他のプログラマーはあなたを獲得しようとはしていませんが、彼らはあなたのコードとやり取りします。変数をプライベートにしないと、彼らは自分のコードでそれを参照するかもしれません。ただし、クラスに戻って何かを変更する必要がある場合は、誰がどの変数をどこで使用するかがわかりません。カプセル化の目的は、クラスの外部インターフェイスを明示的にすることで、これらの(通常)メソッドのみが他のユーザーによって使用されている可能性があることを知ることです。

  1. したがって、プライベート変数は、対応する変数が定義クラスにのみ残るようにします。変更する必要がある場合、変更はクラス自体に対してローカルです。

  2. C ++やJavaなどの従来の言語では、通常、すべてをプライベートにし、対応するゲッターとセッターのみがアクセスできるようにします。本当に決める必要はありません。

  3. 時々、f.ex。C ++構造体では、いくつかのものをグループ化する方法としてのみクラスが必要です。たとえばxy属性のみを持つVectorクラスを考えてみましょう。これらの場合、これらの属性をパブリックと宣言することにより、これらの属性への直接アクセスを許可できます。特に、外部のコードが新しい値を直接xまたはに書き込んでクラスのオブジェクトを変更するかどうかは気にしてはいけませんy

追加のポイントとして、この問題は他の言語ではわずかに異なると見なされることに注意してください。たとえば、関数型プログラミングに強く根ざした言語はデータの不変性を強調します。つまり、データ値はまったく変更できません。そのような場合、他のプログラマー(またはそのコード)がデータに対して行うことを気にする必要はありません。すべてのデータは不変なので、コードに影響を与える可能性のあることは何もできません。

したがって、これらの言語では、統一アクセス原則と呼ばれるものを取得します。この原則では、ゲッターとセッターなどのメソッドを意図的に区別せず、変数/関数への直接アクセスを提供します。したがって、プライベート宣言はオブジェクト指向のシナリオで非常に人気があると言うことができます。

また、知識を広げて他のフィールドを含めることで、既存の概念をまったく新しい方法で表示できることも示しています。


1
+1「他のプログラマーがあなたをつかまえようとしていませんが、彼らはあなたのコードとやり取りします。」コードを使用するプログラマは、本質的に悪ではありません。プライベート変数を使用することで、コードを使用してそれら(および将来、あなた)がけがをしないようにします。また、より良いAPIを設計して文書化するのにも役立ちます。
szalski

7

プライベート変数を使用すると、後でオブジェクトまたは関数のスコープ外の参照が他の変数に誤って影響することはありません。大規模なプログラミングプロジェクトの場合、これは多くの興味深い問題を回避するのに役立ちます(通常はコンパイラーによってキャッチされない)。

たとえば、Javascriptのようなプロトタイプ言語を使用すると、ユーザーは適切と思われる変数を塗りつぶすことができます。

function SomeObject() {
    this.a = 2; //Public (well, actually protected) variable

    this.showA = function() {
        alert(this.a);
    }
}

//Some lines down...

var obj = new SomeObject();
obj.a = 3;
obj.showA(); //Will alert 3. Uh oh!

その変数がプライベートである場合、外部から変更することはできません。

function SomeObject() {
    var a = 2; //Private variable

    this.showA = function() {
        alert(a);
    }
}

//Some lines down...

var obj = new SomeObject();
obj.a = 3;
obj.showA(); //Will alert 2

ただし、すべての変数がプライベートである必要はなく、プライベート変数を過度に使用すると、コードが実際に面倒になります。オブジェクトに重大な影響を与えない些細なフィールドはget()set()メソッドやメソッドを必要としません。

また、プライベート変数を使用すると、多くのパブリック変数が何をするかについての重いドキュメントに頼ることなく、将来コードを簡単に拡張できます。上書きできる変数が少なくなれば、誤って機能を壊すという脅威が少なくなります。

パブリック変数は、オブジェクト/関数が他のオブジェクト/関数にアクセスするときに使用する必要があります。原則として、プライベート変数はこれを実行できないためです。少数からかなりの数のパブリック変数が存在する可能性がありますが、それらが正しく使用されている場合、それらを使用することは悪いことではありません。


3をアラートすることが「あー、ああ!」になる理由は明らかではない。この場合。たぶんそれはプログラマーが望んでいたことです。
イミビス

@immibisおそらく、そしておそらく私は答えをもっと詳しく述べたはずです。ただし、プロパティにアクセスすると、実装の詳細が公開される可能性があるため、オープンクローズ原則やLoDなどのOOP原則に違反する可能性があります。あなたのポイントへのコースは、プロパティが何であるかによって異なります。ほとんどの言語はオブジェクトを参照として使用し、オブジェクトの参照が渡され、他の開発者が静かにプロパティを変更すると、デバッグが非常に難しくなります。IMOクラスインスタンスがある場合、メソッドを使用する方がはるかに簡単で拡張性があります。
ジェフリースウィーニー

7

クラスの将来のメンテナーとユーザーにとっての利点を挙げた良い答えがいくつかあります。ただし、元の設計には利点もあります。あなたの目標が自分自身で物事を簡単にすることであるときと、あなたの目標がクラスユーザーで物事を簡単にすることとの間の明確な境界点を提供します。パブリックとプライベートのどちらかを選択すると、脳に何らかのモードに切り替えるように信号が送られ、最終的にはより良いAPIになります。

プライバシーのない言語がそのような設計を不可能にするわけではありません。代わりのようなものを書くことが要求されることのfoo.getBar()それは書く方が簡単ですので、人々は、ゲッターが必要ではないと思うに傾いているfoo.barが、あなたは、後のような長い怪物で終わるとき、その決定が再訪されていませんobj.container[baz].foo.bar。より厳密な言語で働いたことのないプログラマーは、それが何が悪いのかさえ見ないかもしれません。

そのため、プライバシーのない言語では、すべての「プライベート」メンバーにアンダースコアを付けるなど、それをシミュレートする命名基準を採用することがよくあります。言語がそれを強制しない場合でも、それは有用なシグナルです。


3

絶対にパブリックにする必要がない限り、すべての変数はプライベートにする必要があります(ほとんどの場合、プロパティ/ゲッターとセッターを使用する必要があります)。

変数は主にオブジェクトの状態を提供し、プライベート変数は他のユーザーがオブジェクトの状態に入ったり変更したりすることを防ぎます。


5
主題の方法が狭すぎる。公共の場へのアクセスが必要な場合もありますが、それが望ましい場合もあります
ローランドテップ

状態を変更できないオブジェクト(不変オブジェクト)を設計できますが、これはすべてのクラスに適用される一般的なルールではありません。私の経験では、ほとんどのオブジェクトは、他の人がオブジェクトの状態を簡単に変更できるようにします。
デビッドK 14

1
@DavidK多分、bbbが意図したことは、「プライベート変数が、他の人がオブジェクトの状態を無差別に変更することを防ぐ」ことです。パブリックメソッドは、オブジェクトのプライベート状態を変更できますが、それはオブジェクトの機能に必要かつ一貫した方法でのみです。
マックスナナシー14

@Max Nanasy:はい、パブリックインターフェイスでメソッドのみを提供する場合、状態の変更方法を制御できます。たとえば、オブジェクトが「自己整合」であるために満たす必要があるメンバー間の関係があり、自己整合状態を別の自己整合状態にのみ変更できるようにすることができます。これらの変数がすべてパブリックである場合、これを強制することはできません。しかし変更を許可したくないオブジェクトも存在する可能性があるため、これらのことのどれを話しているのかを明確にすることが重要です。
デビッドK 14

2
  • プライベート変数は何を防ぎますか?

それは、どのプロパティとメソッドがインターフェイスであり、どのプロパティとメソッドが実際にコア機能であるかを明確にすることです。パブリックメソッド/プロパティは、多くの場合、オブジェクトを使用する他の開発者のコ​​ードに関する他のコードに関するものです。同じプロジェクトで100人以上のチームに取り組んだことはありませんが、自分が書いたものを使用して最大20人の開発者と3-5人のチームの経験では、他の懸念はばかげているようです。

注:私は主にJavaScript開発者です。他の開発者が自分のコードを閲覧することを一般的に心配することはなく、彼らはいつでも私のものを単純に再定義できることを完全に認識して動作します。私は彼らが最初に何をしているのかを知るのに十分な能力があると思います。そうでなければ、ソース管理を使用しないチームで作業することはまずありません。

  • 特定のプロパティセットをプライベートにするかどうかをどのように決定しますか?デフォルトですべてのフィールドがプライベートである必要がある場合、クラスにパブリックデータメンバーがあるのはなぜですか?

設定するプロパティの検証やその他の特別な処理を実際に実行していないときに、プライベートプロパティにゲッターとセッターを配置するのはばかげていると思っていました。私はまだそれが常に必要だとは思いませんが、大規模で複雑なものを扱う場合、最も重要なことは、オブジェクトが一貫した方法で動作することに依存している他の多くの開発者が、一貫した均一な方法。呼び出されたメソッドgetThatsetThat、彼らは意図が何であるかを正確に知っており、彼らはトマトではなく常にトマトを得るという期待であなたと対話するオブジェクトを書くことができます。そうでない場合、彼らはあなたのオブジェクトがおそらくするべきではない何かを与えていることを知っています。つまり、他のオブジェクトがおそらくすべきでないそのデータで何かをすることを許可しています。必要に応じて制御できます。

もう1つの大きな利点は、何らかの種類のさまざまな状態コンテキストに基づいて、オブジェクトをゲッターまたはセッターとは異なる方法で渡したり解釈したりするのが簡単になることです。メソッドを使用してユーザーのデータにアクセスしているため、オブジェクトに依存する他のコードを壊すことなく、オブジェクトの動作を後から変更する方がはるかに簡単です。重要な原則は、あなたのオブジェクトだけがあなたが責任を負わせたデータを実際に変更するということです。これは、コードの疎結合を維持するために特に重要であり、移植性と変更の容易さの点で大きな勝利です。

  • どのような状況で変数を公開する必要がありますか?

ファーストクラスの関数(関数を引数として渡すことができます)では、小規模プロジェクトでそうする必要があまりないこと以外に、多くの大きな理由を考えることはできません。それなしでは、他のオブジェクトによって頻繁に頻繁に処理されるメンバーがいて、そのデータ自体に実際に触れていないオブジェクトのgetおよびsetを絶えず呼び出すのは少し面倒に思えるかもしれませんが、それ自体が、なぜオブジェクトがそのデータを担当していたのか不思議に思うでしょう。一般的に言えば、パブリックデータプロパティを決定する前に、アーキテクチャの欠陥を再検討する傾向があります。IMO、通常悪い考えである何かをさせる言語には何の問題もありません。一部の言語は同意しません。


私見、パブリック変数を公開すること唯一の目的とするパブリッククラスを持つことには特に問題はありません。確かに、JVMは、その目的のためのビルトインクラスの数があります:int[]double[]Object[]、などの一つは、しかし、1はそのようなクラスのインスタンスを公開する方法については非常に注意しなければなりません。void CopyLocationTo(Point p);[ Point呼び出し元からa を受け入れる] の意味は、の位置にPoint location()どのような影響Point pt = foo.location(); pt.x ++;があるかが不明であるため、よりも明確ですfoo
supercat

2

SOに関する関連する質問については、この私の投稿をご覧ください。

簡単に言えば、変数スコープを使用すると、コードのコンシューマーが何をすべきか、何をすべきではないかを示すことができます。プライベート変数は、プロパティセッターまたは処理メソッドを使用して、オブジェクト全体が一貫した状態にあることを確認することにより、「吟味」されたデータを保持する場合があります。プライベート変数の値を直接変更すると、オブジェクトの一貫性が失われる可能性があります。プライベートにすることで、誰かが本当に一生懸命働いて、それを変更するために本当に高い実行時許可を持たなければなりません。

したがって、適切なメンバースコーピングは、自己文書化コードの鍵となります。


2

カプセル化の価値について、実際の例を使用して別の観点から説明します。かなり前(80年代前半)に、Dungeons of Daggorathと呼ばれるRadio Shack Color Computer用のゲームが作成されました。数年前、Richard Hunerlachは、紙のアセンブラーリストからC / C ++(http://mspencer.net/daggorath/dodpcp.html)に移植しました。しばらくして、コードを取得し、カプセル化を改善するためにコードをリファクタリングし始めました(http://dbp-consulting.com/stuff/)。

このコードはすでに、スケジューリング、ビデオ、ユーザー入力、ダンジョン作成、モンスターなどを処理するためにさまざまなオブジェクトに組み込まれていますが、アセンブラーから移植されたことが確実にわかります。私の最大の仕事はカプセル化を増やすことでした。つまり、コードのさまざまな部分を取得して、お互いのビジネスから鼻を出すことを意味します。たとえば、ビデオ変数を直接変更して何らかの効果をもたらす多くの場所がありました。ある人はエラーチェックでそれを行い、ある人はそうではなく、そのことの意味が微妙に異なる考えを持っていました。コードの多くの重複がありました。代わりに、ビデオセクションには、目的のタスクを実行するためのインターフェイスが必要であり、そのためのコードはすべて1か所、1つのアイデア、1か所でデバッグできます。そのようなことはramp延していました。

コードがバラバラになり始めたので、診断さえされていなかったバグはなくなりました。コードの品質が向上しました。各タスクはコード内の1つの場所の責任となり、それを正しくするための場所は1つだけでした。(コードをもう一度確認するたびに、さらに多くの情報が見つかります。)

コードについて目に見えるものはすべてインターフェースです。あなたがそれを意味するかどうか。可能な限り可視性を制限すると、後でコードを間違った場所に配置したくなることはありません。コードのどの部分がどのデータを担当するのかが明らかになります。それは、より良く、よりクリーンで、よりシンプルで、よりエレガントなデザインになります。

オブジェクトに独自のデータの責任を負わせ、何かを実行する必要がある他のすべてのユーザーにインターフェイスを提供する場合、コードはより簡単になります。ただ抜け落ちます。1つのことだけを行う小さなシンプルなルーチンがあります。複雑さの軽減==バグの減少。


「私たちのlibユーザーの自由」と「私たちへのトラブルが少ない」の難しいバランス。私は自分のコーディングのバグを防ぐという意味でカプセル化の方が優れていると信じ始めています。そして、エンドユーザーもバグを防ぐ手助けをします。しかし、自由の欠如は、代替手段を探して、単にそれらを片付けるかもしれません...
アクエリアスパワー

リファクタリングされたバージョンがgithubにないのは
残念

2

それは、攻撃の信頼や恐れとは関係なく、カプセル化のみに関するものであり、クラスのユーザーに不必要な情報を強制するものではありません。

プライベート定数を検討してください-秘密の値を含めるべきではありません(他の場所に保存する必要があります)、変更することはできず、クラスに渡す必要はありません(そうでなければパブリックである必要があります)。それらの唯一の可能な用途は、OTHERクラスの定数としてです。しかし、それを行うと、それらのクラスはクラスに依存するようになり、クラスに関係のない作業を行うようになります。定数を変更すると、他のクラスが壊れる可能性があります。それは両方の側から悪いことです-あなたのクラスの作家として、あなたは自由をできるだけ変えたいと思っており、あなたのコントロールの外のものについて心配したくない。クラスの消費者は、クラスの変更やコードの破壊を心配することなく、クラスの公開された詳細に依存できるようにしたいと考えています。

あなたのクラスの消費者は、あなたのクラスと対話するために必要なすべてを知りたいし、彼らのやり方を変えないあなたのクラスについて何も知りたくない:それは役に立たない雑学です。言語をリフレクションで使用している場合、どのように頻繁にそれを使用して、クラスが何かを行う方法や予期せずに例外をスローする場所ではなく、単にプライベートフィールドとメソッドの名前を学習しましたか?私は決して賭けない。あなたはその知識を役に立たないからです。


1

OOPの概念には継承があり、その機能の1つ(JavaまたはC ++)があります。したがって、継承する場合(継承されたクラスの変数にアクセスすることを意味します)、それらの変数に影響を与える可能性があります。したがって、変数を変更できるかどうかを決定する必要があります。

この目的のためだけに、OOPでアクセス修飾子を使用しています。修飾子の1つはprivateです。つまり、そのクラスからのみアクセスできます。他のクラスはこれらの変数に影響を与えることはできません。

知っているように、protectedは、継承しようとしているクラスからアクセスできることを意味します。

OOPに修飾子の概念がある理由は、これらの理由によるものです(どのクラスでも、OOPの概念を使用して他のクラス変数にアクセスできます)。修飾子の概念がない場合は、クラスを継承したり、他のOOPの概念を使用したりするのが困難だったということです。


1

他の人が述べたように、プライベート変数は、オブジェクトを一貫性のない状態に陥らせるミス使用を避け、バグや予期しない例外を追跡するのが難しいのに適しています。

しかし他方では、他の人にほとんど無視されてきたのは、保護されたフィールドに関するものです。

拡張サブクラスは、保護されたフィールドへのフルアクセスを持ち、そのようなフィールドがパブリックであるかのようにオブジェクトを脆弱にしますが、その脆弱性は拡張クラス自体に制限されます(そのようなフィールドをさらに公開しない限り)。

そのため、パブリックフィールドを適切と見なすことは困難であり、現在のところ、それらを使用する唯一の理由は、構成パラメーターとして使用されるクラスのためです(多くのフィールドを持ち、ロジックを持たない非常に単純なクラスです。いくつかの方法)。

しかし一方で、プライベートフィールドは他のユーザーに対するコードの柔軟性を低下させます。

柔軟性とトラブル、長所と短所:

保護されたフィールドを持つバニラクラスのコードによってインスタンス化されたオブジェクトは安全であり、あなたの責任です。

一方、保護されたフィールドを使用してクラスを拡張するオブジェクトは、コードのユーザーによってインスタンス化され、ユーザーの責任ではなくユーザーの責任です。

したがって、十分に文書化されていない保護フィールド/メソッド、またはユーザーがそのようなフィールドとメソッドの使用方法を本当に理解していない場合、自分自身とあなたに不必要なトラブルを引き起こす可能性が十分にあります。

一方、ほとんどのものをプライベートにすると、ユーザーの柔軟性が低下し、物事が起こるようにするためだけにフォークを作成して維持したくない場合があるため、保守された代替手段を探すことさえできなくなります。

ですから、プライベート、保護、パブリックのバランスが本当に重要です。

ここで、プライベートと保護のどちらを選択するかが本当の問題です。

いつ保護を使用しますか?

フィールドが非常に柔軟であると理解するたびに、保護されているとコーディングする必要があります。その柔軟性は、nullになること(nullは常にチェックされ、例外をスローしない有効な状態として認識される)から、クラスexで使用される前に制約を持つことです。> = 0、<100など、値がオーバーフロー/アンダーフローに自動的に固定され、最大で警告メッセージがスローされます。

したがって、そのような保護されたフィールドでは、ゲッターを作成して(フィールド変数を直接使用するのではなく)それだけを使用できますが、他のユーザーはそれを使用しない可能性があります:負の値を拡張クラスで正常に機能させたい場合。


-1

imo @tdammersは正しくなく、実際に誤解を招きます。

実装の詳細を隠すプライベート変数が存在します。クラスAでを使用しarrayてスコアを保存している可能性があります。明日はtreepriority queue代わりにまたはを使用できます。クラスのユーザーが必要とするのは、スコアと名前を入力addScore()する方法と、トップ10が誰であるかを把握する方法getTop(n)です。

基本的なデータ構造にアクセスする必要はありません。いいね?まあ、いくつかの警告があります。

とにかく多くの状態を保存するべきではありません。ほとんどは必要ありません。状態を保存すると、特定のクラスに「分離」されている場合でもコードが複雑になります。別のオブジェクトがそのクラスのメソッドを呼び出したため、プライベート変数が変更された可能性があります。そのメソッドがいつどこで呼び出されたか、そしてそのパブリックメソッドは理論的にはどこでも呼び出せるかどうかを把握する必要があります。

できる最善の方法は、プログラムに含まれる状態の量を制限し、可能な場合は純粋な関数を使用することです。


-1
  • 変数にアクセスするということは、プログラムの実行時にその値にアクセスすることを意味し、変数をプライベートにすると、コードの実行時にその値が保護されます。
  • いわゆる「データ隠蔽」のポイントは、クラスを使用する他のクラスから内部データを隠し続けることです。これらの他のクラスは、変数の値を直接変更するのではなく、クラスのメソッドを呼び出すことによってのみ動作にアクセスする必要があります。
  • 変数をプライベートデータメンバーにすることにより、値が変更または変更されないことをより簡単に保証できます。一方、変数がパブリックの場合、別のクラスが値を変更または変更すると、コードの他の部分がクラッシュする可能性があります。

1
ポイントが作られ、前17件の答えで説明した上で、これはかなりのものを提供していないようだ
ブヨ

-4

最初にオブジェクト指向プログラミングの概念を理解する必要があります。抽象化、カプセル化などがあります。

抽象化-実装の詳細に下線を引く必要なく、ロジックのアイデアを得ることができます。

カプセル化-オブジェクトの下線の実装を確認できません。あなただけがオブジェクトの公開インターフェースを見ることができます。

C#、Java、C ++などのオブジェクト指向プログラムの1つを使用した特定の実装で、これらの概念を実装できます。

private-外の世界から隠されるべき実装。これを変更して、クラスのユーザーが影響を受けないようにします。

public-これは、オブジェクトを使用できるインターフェースです。


1
protected-サブクラス(エクステンダー)(java)から直接アクセスできます。
アクエリアスパワー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.