なぜ言語がこれらを持っているのか、私は少し混乱しています。私は Java プログラマーで、キャリアを始めたばかりなので、Java は、実際に理解し始めて以来、私が書いた唯一の言語です。
したがって、Java ではもちろんプロパティはなく、getThis() および setThat(...) メソッドを記述します。
プロパティを持つことで何を得ることができますか?
ありがとう。
編集:別のクエリ:プロパティを持つ言語で発生する命名規則は何ですか?
なぜ言語がこれらを持っているのか、私は少し混乱しています。私は Java プログラマーで、キャリアを始めたばかりなので、Java は、実際に理解し始めて以来、私が書いた唯一の言語です。
したがって、Java ではもちろんプロパティはなく、getThis() および setThat(...) メソッドを記述します。
プロパティを持つことで何を得ることができますか?
ありがとう。
編集:別のクエリ:プロパティを持つ言語で発生する命名規則は何ですか?
どちらがより自然に見えますか?
// A
person.setAge(25)
// B
person.age = 25;
// or
person.Age = 25; //depending on conventions, but that's beside the point
ほとんどの人はBと答えるでしょう。
これは構文糖衣であるだけでなく、リフレクションを行うときにも役立ちます。メソッドの名前に頼らずに、実際にデータと操作を区別することができます。
プロパティに慣れていない人のために、C# の例を次に示します。
class Person
{
public int Age
{
set
{
if(value<0)
throw new ArgumentOutOfRangeException();
OnChanged();
age = value;
}
get { return age; }
}
private int age;
protected virtual void OnChanged() { // ... }
}
また、ほとんどの人は、常に get/set を使用するのと同じ理由で、パブリック メンバーを後でプロモートするのではなく、常にプロパティを使用します。データ メンバーにバインドされた古いクライアント コードを書き直す必要はありません。
構文ははるかに優れています。
button.Location += delta;
よりも:
button.setLocation(button.getLocation() + delta);
編集:
以下のコードは、すべてを手動で行っていることを前提としています。私の例の世界では、コンパイラは単純な get/set メソッドを生成し、すべての直接変数アクセスをそれらのメソッドに変換します。そうでない場合は、クライアント コードを再コンパイルする必要があり、目的の大部分が無効になります。
オリジナル:
プロパティの主な議論は、変数からメソッドに移行する場合にコードを再コンパイルする必要がなくなるということです。
例えば:
public class Foo
{
public int bar;
}
後で検証を「禁止」することにした場合は、次のようにする必要があります。
public class Foo
{
private int bar;
public void setBar(final int val)
{
if(val <= 0)
{
throw new IllegalArgumentException("val must be > 0, was: " + val);
}
bar = val;
}
public int getBar()
{
return (bar);
}
}
しかし、set/get メソッドを追加すると、すべてのコードが壊れてしまいます。プロパティを介して行われた場合は、クライアント コードを壊すことなく、事後に検証を追加できます。
私は個人的にこのアイデアが好きではありません - 私は注釈を使用し、必要に応じて独自のセット/取得実装を提供する機能を備えた単純なセット/取得を自動的に取得するというアイデアに非常に満足しています (ただし、隠しメソッドは好きではありません)呼び出します)。
2 つの理由:
Java では、ゲッターとセッターは本質的にプロパティです。
他の現代言語 (c#) などでは、構文の操作/理解が容易になります。
それらは不要であり、ほとんどの場合、回避策があります。
それは本当に好みの問題ですが、使用している言語がそれらをサポートしている場合は、それらを使用することをお勧めします:)
私も最初はこれに苦労しましたが、本当に感謝しています。私の見方では、プロパティを使用すると、ゲッター/セッター メソッドによって提供されるカプセル化を失うことなく、公開されたデータを自然な方法で操作できます。つまり、プロパティをフィールドとして扱うことができますが、そうしないことを選択した場合、実際のフィールドを実際に公開することはありません。C# 3.0 の自動プロパティを使用すると、ほとんどのフィールド (コンシューマーがデータを読み書きできるようにしたい場合) についてさらに良くなります。書き込む必要はさらに少なくなります。
public string Prop { get; set; }
部分的な可視性が必要な場合は、必要なアクセサーだけを簡単に制限できます。
public string Prop { get; private set; }
これはすべて getter/setter メソッドで実行できますが、言い回しがはるかに多くなり、使用法があまり自然ではなくなります。
オブジェクト指向プログラミングの一般的なルールは、既存のインターフェイスを変更しないことです。これにより、オブジェクトを呼び出しているオブジェクトがこれを知る必要がないため、内部コンテンツが変更される可能性があります。
他の言語のプロパティは、特定の言語機能を装ったメソッドです。Java では、プロパティは慣例によってのみ区別されます。一般的にこれは機能しますが、制限される場合があります。たとえば、getSomething の isSomething の代わりに hasSomething を使用することがあります。
そのため、名前に柔軟性があり、依存するツールやその他のコードは依然として違いを伝えることができます。
また、コードをよりコンパクトにすることができ、get と set は設計によってグループ化されます。
Object Oriented Software Construction 2で、Bertrand Meyer はこれを「Uniform Access Principle」と呼んでいます。一般的な考え方は、プロパティが単純なもの (つまり、単なる整数) から派生したもの (関数呼び出し) に変わるとき、それを使用する人々はそれを使用するということです。知らなくていい。
コードを使用しているすべての人が変更する必要はありません。
int x = foo.y;
に
int x = foo.y();
「実装」だけで「インターフェース」を変更していないため、カプセル化が壊れます。
派生フィールドと読み取り専用/書き込み専用フィールドを作成することもできます。私が使用した言語で見たほとんどのプロパティでは、単純なフィールドだけでなく、完全な機能をプロパティに割り当てることができます。
プロパティは、オブジェクト内の一連のロジックの背後にある詳細を単一の値に抽象化して外の世界に伝える簡単な方法を提供します。
プロパティは値としてのみ開始される場合がありますが、この抽象化によりインターフェイスが分離され、後で最小限の影響で詳細を変更できるようになります。
一般的な経験則では、抽象化と疎結合は良いことです。プロパティは両方を実現するパターンです。
バインディングがすべてです
私がプロパティを単なる構文糖衣だと考えていた時期がありました (つまり、型を少し減らすことで開発者を助けます)。GUI の開発を重ね、バインディング フレームワーク (JGoodies、JSR295) を使い始めると、言語レベルのプロパティは構文糖衣以上のものであることがわかりました。
バインディング シナリオでは、基本的に、「オブジェクト A のプロパティ X は常にオブジェクト B のプロパティ Y と等しくなければならない」というルールを定義します。省略形: Ax <-> By
では、実際に Java でバインディング ライブラリを作成する方法を想像してみてください。現在、「x」または「y」を言語プリミティブとして直接参照することは絶対に不可能です。それらは文字列としてのみ参照できます(そしてリフレクションを介してアクセスできます)。要するに、A."x" <-> B."y"
これは、コードをリファクタリングするときに、非常に大きな問題を引き起こします。
プロパティ変更通知の適切な実装など、追加の考慮事項があります。私のコードを見ると、祝福されたすべてのセッターは、信じられないほど単純なことを行うために最低 3 行を必要とします。さらに、これらの 3 行のうちの 1 行には、さらに別の文字列が含まれています。
public void setFoo(Foo foo){
Foo old = getFoo();
this.foo = foo;
changeSupport.firePropertyChange("foo", old, foo);
}
浮かんでいるこれらの文字列はすべて完全な悪夢です。
ここで、不動産がその言語の第一級市民であると想像してみてください。これにより、ほぼ無限の可能性が提供され始めます (たとえば、PropertyChangeSupport をいじる代わりに、リスナーを Property に直接登録することを想像してください。これは、すべてのクラスに追加する必要がある 3 つの謎のメソッドです)。プロパティ自体 (プロパティの値ではなく、Property オブジェクト) をバインディング フレームワークに渡すことができると想像してください。
Web 層の開発者は、プロパティ自体の名前 (registerFormProperties(myObject.firstname, myObject.lastname, someOtherObject.amount) のようなもの) から独自のフォーム ID 値を構築して、オブジェクトのラウンドトリップ ポピュレーションを可能にする Web フレームワークを想像してください。フォームがサーバーに送信されたときのプロパティ値現在、これを行うには、文字列を渡す必要があり、リファクタリングは頭痛の種になります (文字列とリフレクションに依存して物事を結び付けると、リファクタリングは実際には実に恐ろしいものになります) )。
とにかく、バインディングを介して動的なデータ更新を扱っている私たちにとって、プロパティは言語で非常に必要とされている機能です。単なる構文糖衣以上のものです。