开发者

Where's the Encapsulation?

I'm a new programmer, so please excuse any dumbness of this question, how the following code is encapsulating pri开发者_C百科vate data? -

public class SomeClass
{
    private int age;

    public int Age
    {
        get { return age; }
        set { age = value; }
    }

    public SomeClass(int age)
    {
        this.age = age;
    }
}

I mean, with no restriction logic or filtering logic in the properties, how is the above code different from the folowing one -

public class SomeClass
{
    public int age;

    public SomeClass(int age)
    {
        this.age = age;
    }
}

Is the first code providing any encapsulation at all?


It's providing one piece of encapsulation: it's saying, "there's an Age property you can get and set, but I'm not going to tell you how I'm implementing it."

That's not very strong encapsulation, but it does keep the implementation details separate from the public API. Without changing the public API at all, you could start to store the age somewhere else - in two short fields, in a service somewhere, as part of a long field or whatever. You could put logging in the property to see how often it's used. You could add an event which gets fired when the age changes (that's an API change, but won't break existing callers).

EDIT: One thing to note: even though this does nothing now, the change to make it do something later is both source and binary compatible. Changing a field to become a property is not backward compatible, either in source or binary forms. In most cases it will be source-compatible, but not binary-compatible. In some cases source will no longer build. In more evil (and contrived, admittedly) both versions will build, but with different effects.

Also note that as of C# 3, you can declare a trivial property as easily as a field:

public int Age { get; set; }

I have an article about all of this which provides more details.


This is a bit of a vacuous example. As you've correctly noted, the property doesn't seem to do anything.

But it could. For example, SomeClass could put restrictions on how the Age property is modified (by say not changing the age to a bad value like -2 or 823). Also, SomeClass need not represent age as an int internally. Age could be the result of a computation (by say subtracting today's date from a person's date of birth) or it could be stored within SomeClass as another data type (say a byte, long or a double).


I mean, with no restriction logic or filtering logic in the properties, how is the above one different from the folowing one

Its not the fact that you have or have not implemented the validation logic in the property, encapsulation here means that nobody can directly access/modify your private data. The only access available is to go through the property.

Using the bottom code, anyone can genereate exceptions and cause all kinds of havoc because they can do anything they want to your data.

Using the top code as its written allows this same havoc, but at any time in the future you can implement restriction logic in the Property and not have to modify an API for users of this class.


It's encapsulating, or wrapping, changes to the private variable age. Private variable Age can't be modified by external callers directly, only through the public methods given. It's setting up an interface so future changes to age won't break callers. The benefit is to external callers in the future, which is why it's hard to see now.


In your first example, SomeClass.Age is a property. The field "backing" the property is private. In your second example, SomeClass.age is a public field. While in many cases there may be no difference, choosing a property over a field gives you the ability to change the implementation without changing the API, or "shape" of the class. Maybe you want to do something (persist, or notify) whenever the property changes -- that would be impossible to do with a field.


Is the first code providing any encapsulation at all?

NO (at least the particular code you wrote).

The 2 pieces of code are almost the same. The first one doesn't provide any useful difference compare to the second one (as the code is written).

When using getters and setters, you can restrict access to the private variables. This could be a form of Encapsulation.

i.e.

private int x

public int getInt(String password){
 if(password == 'RealPassword'){
   return x
  }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜