When should a class use its own getters/setters vs

2019-02-04 14:49发布

问题:

When generating setters and getters in Eclipse one of the options is to use the getters and setters within the class rather than accessing the class members directly. Is this level of class internal encapsulation useful or is it taking a good idea one step too far?

DUPE: Should you use accessor properties from within the class, or just from outside of the class?

回答1:

I think it's a good idea if you want the potential side-effects to occur - validation, logging etc. (In C# I'd like to be able to declare a variable and property and say that the only access to the variable is through the property.)

Occasionally you may well find you need to set the variable directly precisely because you don't want the side-effects. For instance, you may need to set two variables together, and both the "before" and the "after" states are valid, but setting either property individually would make validation blow up.



回答2:

It can be useful, if you allow derived classes to re-define your getters. So, using getters even from inside the class will keep your design extensible.

In my opinion this is something that needs to be defined in the coding guidelines.



回答3:

The short answer is "it depends" :)

Eric Lippert has an excellent article on Automatic vs. Explicit properties that deals with this issue, albeit from a slightly different angle.

Essentially, the question you need to ask is:

"From within the class, [are] the desired semantics of accessing this ... property different from the desired semantics of accessing the property from the outside?"

If the semantics are the same, your class should use its own properties. If the semantics are different, your class will need to directly manipulate the backing fields.



回答4:

It's useful for example when you have setters which do extra actions like setting a dirty flag or notifying observers.

For getters you may instead of accessing a field compute a value when you change representation.



回答5:

When you need to extend the getter/setter behavior of a class, it is useful have encapsulated fields (getters/setters instead of direct member access). Yet in inheritance, it is conceptualy interesting to preserve the inners of your class, if its subclasses shouldn't be aware of its private stuff. So, sometimes the field is private to the implementation of a class, so that even the subclasses aren't aware of it.



回答6:

I find that I do that at times - specifically when I require, or strongly anticipate that I'll require, some login around getting or setting (and the validation around them) of members.

I find that having private/internal properties does help in these cases.

But I certainly not do it for any memeber.

Latest .NET/VS really helps here as you can declare a property as such:

public string SomeProperty
{
get;
set;
}

and it effectively creates the memebr behind the scene. I know that doesn't help you, but I thought it might be of some interest :-)



回答7:

If you want for this member to be databindable by either Winform or WPF, I believe that you need to declare it as a property. I'm about 95 percent positive that databinding requires a property (getter/setting syntax). I have a small wpf solution that demonstrates this, but I don't see a way to attach it here.

Here's the code: (built with VS 2008 SP1, targeting .net 3.5 - I used a WPF Project). There are 2 items in the WPF project, the main window (window1), and the object that we are testing (DataObject) There is a label on the window that is databound to the Name property in an instance of data object. If you convert the Name property to a field (remove the getter/setter), the databinding will stop working.

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;
        }
    }
}