Eclipseでセッターとゲッターを生成する場合、オプションの1つは、クラスメンバーに直接アクセスするのではなく、クラス内でゲッターとセッターを使用することです。このレベルのクラス内部カプセル化は有用ですか、それとも一歩先を行くのは良い考えですか?
7 に答える
潜在的な副作用(検証、ロギングなど)を発生させたい場合は、良い考えだと思います(C#では、変数とプロパティを宣言し、変数への唯一のアクセスは財産。)
場合によっては、副作用が必要ないため、変数を正確に直接設定する必要があることに気付くかもしれません。たとえば、2 つの変数を一緒に設定する必要があり、「前」と「後」の両方の状態が有効ですが、いずれかのプロパティを個別に設定すると検証が失敗します。
簡単な答えは「状況によって異なります」です:)
Eric Lippertは、わずかに異なる角度からではありますが、この問題を扱う自動プロパティと明示プロパティに関する優れた記事を掲載しています。
基本的に、あなたが尋ねる必要がある質問は次のとおりです。
「クラス内から、この...プロパティにアクセスするための望ましいセマンティクスは、外部からプロパティにアクセスするための望ましいセマンティクスとは異なりますか?」
セマンティクスが同じである場合、クラスは独自のプロパティを使用する必要があります。セマンティクスが異なる場合、クラスはバッキングフィールドを直接操作する必要があります。
派生クラスがゲッターを再定義できるようにする場合に役立ちます。そのため、クラス内からでもゲッターを使用すると、設計の拡張性が維持されます。
私の意見では、これはコーディング ガイドラインで定義する必要があるものです。
たとえば、ダーティ フラグの設定やオブザーバーへの通知などの追加のアクションを実行するセッターがある場合に役立ちます。
ゲッターの場合、表現を変更するときに、フィールドにアクセスする代わりに値を計算できます。
特に、メンバーの取得または設定 (およびその周りの検証) に関するログインが必要な場合、または必要になることが強く予想される場合はそうします。
これらの場合、プライベート/内部プロパティを持つことが役立つことがわかりました。
しかし、私は確かにメンバーのためにそれをしません.
最新の .NET/VS は、プロパティを次のように宣言できるため、ここで非常に役立ちます。
public string SomeProperty
{
get;
set;
}
舞台裏でメンバーを効果的に作成します。役に立たないことはわかっていますが、少しは興味があるかもしれないと思いました:-)
クラスの getter/setter 動作を拡張する必要がある場合、フィールドをカプセル化すると便利です (直接メンバー アクセスではなく、getter/setter)。しかし、継承では、サブクラスがそのプライベートなものを認識してはならない場合、クラスの内部を保持することは概念的に興味深いものです。そのため、フィールドがクラスの実装に対してプライベートであるため、サブクラスでさえそれを認識しない場合があります。
このメンバーを Winform または WPF でデータバインド可能にしたい場合は、プロパティとして宣言する必要があると思います。私は、データ バインディングにはプロパティ (getter/setting 構文) が必要であることを約 95% 確信しています。これを示す小さな wpf ソリューションがありますが、ここに添付する方法がわかりません。
コードは次のとおりです(VS 2008 SP1で構築され、.net 3.5をターゲットにしています-私はWPFプロジェクトを使用しました)。WPF プロジェクトには、メイン ウィンドウ (window1) と、テストするオブジェクト (DataObject) の 2 つの項目があります。ウィンドウには、データ オブジェクトのインスタンスの Name プロパティにデータ バインドされたラベルがあります。Name プロパティをフィールドに変換する (getter/setter を削除する) と、データバインディングが機能しなくなります。
Window1.xaml:
<Window x:Class="WpfDatabinding.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Label Name ="Label1" Height="28" Margin="12,24,37,0" VerticalAlignment="Top" Content="{Binding Name}"></Label>
</Grid>
Window1.xaml.cs
using System;
using System.Windows;
namespace WpfDatabinding
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
private DataObject ADataObject;
public Window1()
{
InitializeComponent();
this.ADataObject = new DataObject();
this.ADataObject.Name = "Hello!";
this.DataContext = this.ADataObject;
}
}
}
namespace WpfDatabinding
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
private DataObject ADataObject;
public Window1()
{
InitializeComponent();
this.ADataObject = new DataObject();
this.ADataObject.Name = "Hello!";
this.DataContext = this.ADataObject;
}
}
}
DataObject.cs:
namespace WpfDatabinding
{
public class DataObject
{
// convert this to a field, and databinding will stop working
public string Name
{
get;
set;
}
}
}