Кога класът трябва да използва свои собствени гетери/сетери срещу директен достъп до членовете?

Когато генерирате сетери и гетери в Eclipse, една от опциите е да използвате гетерите и сетерите в рамките на класа, вместо да осъществявате директен достъп до членовете на класа. Полезно ли е това ниво на вътрешно капсулиране на класа или прекалява с добрата идея?

DUPE: Трябва ли да използвате свойства на аксесора от класа или просто извън класа?


person stimms    schedule 25.02.2009    source източник
comment
възможен дубликат на Трябва използвате свойства на аксесора от класа или просто извън класа?   -  person nawfal    schedule 04.06.2013


Отговори (7)


Мисля, че е добра идея, ако искате да се появят потенциалните странични ефекти - валидиране, регистриране и т.н. (В C# бих искал да мога да декларирам променлива и свойство и да кажа, че само достъпът до променливата е чрез свойството.)

Понякога може да откриете, че трябва да зададете променливата директно точно защото не искате страничните ефекти. Например, може да се наложи да зададете две променливи заедно и двете състояния „преди“ и „след“ са валидни, но настройването на което и да е свойство поотделно би направило проверката взривена.

person Jon Skeet    schedule 25.02.2009

Може да бъде полезно, ако позволите на производните класове да предефинират вашите гетери. Така че използването на гетъри дори от вътрешността на класа ще запази вашия дизайн разширяем.

Според мен това е нещо, което трябва да бъде определено в насоките за кодиране.

person Joachim Sauer    schedule 25.02.2009

Краткият отговор е "зависи" :)

Eric Lippert има отлична статия за Automatic срещу изрични свойства, който се занимава с този проблем, макар и от малко по-различен ъгъл.

По същество въпросът, който трябва да зададете, е:

„От рамките на класа [дали] желаната семантика за достъп до това ... свойство е различна от желаната семантика за достъп до свойството отвън?“

Ако семантиката е същата, вашият клас трябва да използва свои собствени свойства. Ако семантиката е различна, вашият клас ще трябва директно да манипулира резервните полета.

person AwesomeTown    schedule 25.02.2009

Полезно е например, когато имате сетери, които извършват допълнителни действия като задаване на мръсен флаг или уведомяване на наблюдатели.

За getters можете вместо достъп до поле да изчислите стойност, когато промените представянето.

person starblue    schedule 25.02.2009

Когато трябва да разширите поведението на getter/setter на даден клас, е полезно да имате капсулирани полета (getters/setter вместо директен достъп до членове). И все пак при наследяването е концептуално интересно да запазите вътрешността на вашия клас, ако неговите подкласове не трябва да са наясно с личните му неща. Така че понякога полето е частно за имплементацията на клас, така че дори подкласовете не знаят за това.

person rcaval    schedule 12.03.2009

Откривам, че го правя понякога - особено когато изисквам или силно очаквам, че ще изисквам някакво влизане във връзка с получаването или настройката (и валидирането около тях) на членове.

Намирам, че наличието на частни/вътрешни свойства помага в тези случаи.

Но със сигурност не го правя за който и да е член.

Последният .NET/VS наистина помага тук, тъй като можете да декларирате свойство като такова:

public string SomeProperty
{
get;
set;
}

и ефективно създава спомен зад сцената. Знам, че това не ти помага, но си помислих, че може да ти е интересно :-)

person Yossi Dahan    schedule 25.02.2009

Ако искате този член да може да се обвързва с данни или от Winform, или от WPF, смятам, че трябва да го декларирате като свойство. Около 95 процента съм сигурен, че обвързването на данни изисква свойство (синтаксис за получаване/настройка). Имам малко wpf решение, което демонстрира това, но не виждам начин да го прикача тук.

Ето кода: (създаден с VS 2008 SP1, насочен към .net 3.5 - използвах WPF проект). Има 2 елемента в проекта WPF, основният прозорец (window1) и обектът, който тестваме (DataObject). Има етикет на прозореца, който е свързан с данни към свойството 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;
        }
    }
}
person JMarsch    schedule 25.02.2009