誰もが知っているように、Javaはオブジェクト指向のパラダイムに従います。データのカプセル化では、オブジェクトのフィールド(属性)は外界に対して非表示にし、メソッドを介してのみアクセスする必要があります。 のみ外界のクラスのインターフェース。では、なぜJavaのフィールドをパブリックとして宣言できるのでしょうか。これは、データカプセル化パラダイムに反するのでしょうか。
すべてのルールには例外があり、特定の場合にはすべてのベストプラクティスが上書きされる可能性があるため、それは可能だと思います。
たとえば、パブリック静的最終データメンバーをパブリック(定数など)として公開することがよくあります。有害ではないと思います。
この状況は、Java以外の他の言語(C++、C#など)にも当てはまることを指摘しておきます。
言語は必ずしも私たちを自分自身から守る必要はありません。
Oliの例では、このように書くとどのような害がありますか?
public class Point {
public final int x;
public final int y;
public Point(int p, int q) {
this.x = p;
this.y = q;
}
}
それは不変でスレッドセーフです。データメンバーは公開されている可能性がありますが、それらを傷つけることはできません。
その上、「プライベート」がJavaで実際にプライベートではないことは、汚い小さな秘密です。いつでもリフレクションを使用して回避できます。
だからリラックスしてください。そう悪くはない。
柔軟性のために。私が書くことができなかったら、それは大きな苦痛でしょう:
class Point {
public int x;
public int y;
}
これをゲッターとセッターの後ろに隠すことには、貴重な利点はほとんどありません。
厳密な「データカプセル化」だけがパラダイムではなく、オブジェクト指向の必須機能でもないためです。
さらに、パブリックセッターメソッドとパブリックゲッターメソッドを持つデータ属性があり、それらのメソッドが実際に属性を設定/取得する以外に何もしない場合、それをプライベートに保つことのポイントは何ですか?
すべてのクラスがカプセル化パラダイムに従うわけではありません(例:ファクトリクラス)。私にとって、これは柔軟性を高めます。そしてとにかく、適切にスコープするのは言語ではなくプログラマーの責任です。
パブリック変数の良い面について議論しています...好きです... :)
public
変数を使用する理由はたくさんあります。それらを1つずつ確認してみましょう。
パフォーマンス
まれですが、それが重要になる状況がいくつかあります。場合によっては、メソッド呼び出しのオーバーヘッドを回避する必要があります。
定数
定数にはパブリック変数を使用できますが、コンストラクターで初期化した後は変更できません。パフォーマンスにも役立ちます。これらは、データベースへの接続文字列のように、静的定数である場合があります。例えば、
public static final String ACCEPTABLE_PUBLIC = "Acceptable public variable";
その他の場合
public
で違いがない場合や、ゲッターとセッターが不要な場合があります。 Point
の良い例は、すでに答えとして書かれています。
オブジェクト指向設計には、カプセル化の要件はありません。これは、OOよりも言語の設計にはるかに関係するJavaのような言語でのベストプラクティスです。
単純な理由の1つとして、常にJavaにカプセル化することをお勧めします。カプセル化しないと、オブジェクトの署名を変更せずに後でカプセル化することはできません。たとえば、従業員の場合名前があり、公開すると、employee.nameになります。後でカプセル化する場合は、employee.getName()とemployee.setName()になります。もちろん、これにより、Employeeを使用するコードが破損します。したがって、Javaでは、すべてをカプセル化することをお勧めします。これにより、オブジェクトの署名を変更する必要がなくなります。
他のいくつかのOO言語(ActionScript3、C#など)は、ゲッター/セッターを追加しても署名に影響を与えない真のプロパティをサポートします。この場合、ゲッターまたはセッターがある場合は、それが置き換えられます。同じ署名を持つパブリックプロパティなので、コードを壊すことなく簡単に切り替えることができます。これらの言語では、常にカプセル化する必要はありません。
Javaは、Cスタイルの構文言語からの分岐です。これらの言語は、一般に「1つのアイテム」と見なされると判断されたメモリブロックの固定オフセットエイリアスであるstruct
sをサポートしていました。言い換えると、データ構造はstruct
sで実装されました。
構造体を使用すると、オブジェクト指向プログラミングのカプセル化の目標に直接違反しますが、Javaが最初にリリースされたとき、ほとんどの人は反復(手続き型)プログラミングではるかに有能でした。メンバーをpublic
として公開することで、効果的に使用できます。 a Javaクラスは、2つの環境の基本的な実装が大幅に異なっていても、Cstruct
を使用するのと同じ方法です。
適切なカプセル化でこれを行うことができるシナリオがいくつかあります。たとえば、多くのデータ構造は2つ以上のポインタのノードで構成され、1つは「含まれる」データを指し、1つ以上は残りのデータ構造への「その他の」接続を指します。このような場合、「データ構造」クラスの外部に表示されないプライベートクラス(内部クラスなど)を作成する可能性があります。構造をウォークするすべてのコードは同じ_.Java
_ファイルに含まれているためです。 、パフォーマンスの最適化として、内部クラスの.getNext()
メソッドを削除できます。
怠惰以外でゲッターやセッターを使わない理由は本当に考えられません。これまでで最高のJava本の1つと広く見なされている効果的なJavaは、常にゲッターとセッターを使用するように言っています。なぜ常にゲッターとセッターを使用する必要があるのかを聞く必要がない場合この段落をスキップします。ゲッターとセッターを使用しない時間としてのポイントの1番目の回答の例に同意しません。これにはいくつかの問題があります。番号のタイプを変更する必要がある場合はどうなりますか。たとえば、1回グラフィックを試していたところ、天気について頻繁に考えを変えて、場所をJava Shapeに保存するか、彼が示したように直接intとして保存したい。使用しなかった場合ゲッターとセッターと私はこれを変更しましたが、場所を使用するすべてのコードを変更する必要がありましたが、変更しなかった場合は、ゲッターとセッターを変更するだけで済みました。
ゲッターとセッターはJavaの苦痛です。 Scalaでは、APIを変更せずに、パブリックデータメンバーを作成し、後でゲッターやセッターを作成できます。これにより、両方の長所が得られます。おそらく、Java =これはいつか修正されます。
アクセシビリティ修飾子は、OO言語でのカプセル化の概念の実装です(この実装は、この概念を緩和し、ある程度の柔軟性を可能にする方法だと思います)。純粋なOOアクセシビリティ修飾子を持たない言語、つまりSmalltalk。この言語では、すべての状態(インスタンス変数)はプライベートであり、すべてのメソッドはパブリックです。オブジェクトの状態を変更または照会する必要がある唯一の方法は、インスタンスメソッド。メソッドにアクセシビリティ修飾子がないため、開発者は特定の規則を採用する必要があります。たとえば、プライベートプロトコルのメソッド(プロトコルはクラス内のメソッドを整理する方法です)はクラス外で使用しないでください。言語はこれを強制します。必要に応じて、これらのメソッドを呼び出すことができます。
Publicを使用するかどうかは、維持する不変条件があるかどうかによって異なります。たとえば、純粋なデータオブジェクトは状態遷移を制限しないため、データメンバーをパブリックとして公開する機能を提供しない一連のアクセサーでメンバーをカプセル化することは意味がありません。
取得と設定以外の機能を提供しない特定の非プライベートデータメンバーのゲッターとセッターの両方がある場合は、デザインを再評価するか、メンバーを公開することをお勧めします。
データのカプセル化は、必須の要件やルールではなく、アドオン機能のように提供されると思います。そのため、コーダーは、自分の知恵を使って機能を適用し、必要に応じて微調整する自由が与えられます。したがって、柔軟に対応できます。です!
関連する例は、@ OliCharlesworthによって与えられたものです。
私は初心者ですが、publicステートメントが存在しない場合、Java開発は理解するのが非常に複雑になります。コードの理解を単純化するためにpublic、privateなどのステートメントを使用するためです。 、私たちが使用している瓶や他の人が作成した瓶のように。私が言いたいのは、私たちは発明する必要はなく、学び、継続する必要があるということです。
私は英語からお詫びすることを望みます、私は改善しようとしています、そして私は将来はっきりと書くことを望んでいます。