12

これは他の場所で回答されていると確信しているので、謝罪することから始めます-私が理解している方法でそれを説明する回答が見つかりません! 私は修士課程の変換コースを行っていますが、これを含め、まだ苦労しているいくつかの基本的な基本があります-変​​数をプライベートにする方が良い理由.

print メソッドを持つ Person という Java クラスがあるとします。私はそれを作成し、そのように定義することができました:

public class Person
{
    public String name;
    public String telephoneNumber;

    public void print()
    {
       System.out.println(name + " " + telephoneNumber);
    }
}

次に、メイン クラスで、次のコードを記述できます。

class testPerson
{
  public static void main(String[] args)
  {
    Person test;
    test = new Person();

    test.name = "Mary";
    test.telephoneNumber = "01234 567890";

    test.print();
  }
}

これを行った場合、test.print(); 出力が生成されます。

mary 01234 567890

ただし、これは不適切なコーディングと見なされます。変数は、パブリック クラス内でプライベートにする必要があります。これは、この情報がどのように格納されているかを人々に見せたり、承認なしに情報を編集したりできないようにするためです。

そこで、Person クラスを編集して 2 つの Strings をプライベートに宣言し、次のように get メソッドと set メソッドを追加します。

private String name;
private String telephoneNumber;

public void setName (String name)
{
  this.name = name;
}

public void getName()
{
  return name;
}

// same code for telephone methods.

ここで、メイン クラスで、名前と電話を設定するメソッドを次のように変更します。

mary.setName("Mary");
mary.settelephoneNumber("01234 567890");

私がフォローしているレクチャー ノートによると、これはより効率的です (ただし、Person() メソッドを追加してインスタンス化などを可能にすることでさらに効率的にすることができます)。

しかし、なぜこれが優れているのかを理解するのに苦労しています。
前者の方法では、ユーザーは変数に直接アクセスできました。ただし、直接アクセスできない変数を非表示にしても、ユーザーは間接的にアクセスして変更することができ、まったく同じ結果が得られます。

これが好まれるのはなぜですか、そして間違いなく愚かなことは何ですか?

4

5 に答える 5

30

ピザ配達の例え

  1. あなたは配達のためにピザを注文します。
  2. ピザの男の子がドアをノックし、あなたがそれを支払うことを期待しています。
  3. あなたは財布からお金を取り出して配達員に渡します。(あなたは内部の詳細(運転免許証など)を隠すことを管理しています)あるいは、
    • あなたは配達員に財布を渡して、彼にそれからお金を取るように頼むことができます。これを行うことにより、あなたはもはやコントロールできなくなります。内部の詳細を公開しています。

情報隠蔽カプセル化について読むことは情報隠蔽ではありません。

于 2013-02-04T20:34:26.063 に答える
14

より効率的であるということではなく、より保守しやすく、優れたプラクティスであるということです。

たとえば、setter メソッドを使用すると、実際に設定を行う前に、有効な電話番号であるsetTelephoneNumberことを実際に確認することができます。String変数を公開した場合、おそらくそれはできませんでした。最初からセッターを使用するということは、戻って後で検証を追加できることを意味しますが、変数をパブリックにした場合は、セッターを追加し、すべてのユーザーを変更して、変数を変更する代わりにセッターを使用する必要があります。直接変数。

于 2013-02-04T20:28:37.707 に答える
5

人々はあなたにそれがより良い理由を百万の逆流した理由を与えるでしょう、しかしそれはいくつかの場合にのみより良く、それらのすべてが明白にではありません。たとえば、Java独自のクラスGridBagConstraints考えてみましょう。メソッドはまったくありません(カウントしない場合はclone、とにかく持っています。すべてのJavaクラスはそれを継承しますObject)。なんで?これが実際にはもっと実用的である場合があるからです。そしてGridBagConstraints、最も純粋な意味でのJava Beanです。これはすべてプロパティに関するものであり、ビジネスロジックはありません。

実践からの別の事実について報告させてください。セッターがその入力を検証することはありません。ゲッターがその結果を計算することはありません。JavaBeansの世界では、そのような動作はすぐに、セッターが設定する普遍的な仮定の邪魔になり、ゲッターはを取得します。基本的に、パブリックフィールドとまったく同じものから何らかの形で分岐すると、負けます。

Hibernateのような最新のJavaAPIは、JavaBeanスタイルのプロパティと同等の立場で裸のパブリックフィールドを受け入れることにより、この事実を認めています。以前のバージョンではそれができませんでしたが、Javaの経験が増えるにつれて、パブリックフィールドはOKであるという認識がついに始まりました。

于 2013-02-04T20:34:04.753 に答える
2

ある時点で、他の誰かがあなたのコードを使用するだろうという前提に基づいて操作する必要があります。クラスのパブリック プロパティが表示された場合は、自由に操作できると想定できるはずです。直接変更しない場合は、外部から参照できないはずです。

文字通りの良い例は、ビットマップ オブジェクトの寸法です。寸法が -10x-10 のビットマップを描画しようとすると、ほとんどのマシンはそれを好まないでしょう。このビットマップの幅/高さのプロパティが単なるパブリック変数である場合、後で善意のコーダーによって無効な値に設定される可能性があります (決して起こらないと仮定しないでください)。バン、フリーズしたコンピューターを手に入れました。

変数を非表示にしてセッターを使用することで、これが起こらないようにすることができます。

private int _width = 10;

public void setWidth(int value)
{
     //Prevent the value moving into invalid range:

     if(value < 1)
          value = 1;

     if(value > 4096)
          value = 4096;

     //Now apply it
     _width = value;
}

ただし、速度と利便性のために、最初はこのようにコードを開発する必要はありません。後でコードを確認し、必要なものを非表示にしてください。

于 2013-02-04T20:51:04.490 に答える
0

考慮すべきセキュリティ上の問題もあります。一般的な例は銀行口座です。残高があり、デポジットを使用してお金を入れ、引き出しを使用してお金を削除します。残高が公開されている場合、お金を預けたり引き出したりすることなく変更できます。それは非常に悪いかもしれません。

メソッド内で、実際に存在する以上のお金を口座から引き出さないようにするなど、物事をチェックすることができます。値に直接アクセスしている場合は、実際にはできません。それはコントロールについてです。

于 2013-02-04T20:36:47.673 に答える