封装在哪里?
我是一个新程序员,所以请原谅这个问题的任何愚蠢之处,以下代码是如何封装私有数据的? -
public class SomeClass
{
private int age;
public int Age
{
get { return age; }
set { age = value; }
}
public SomeClass(int age)
{
this.age = age;
}
}
我的意思是,如果属性中没有限制逻辑或过滤逻辑,上面的代码与下面的代码有何不同 -
public class SomeClass
{
public int age;
public SomeClass(int age)
{
this.age = age;
}
}
第一个代码是否提供任何封装?
I'm a new programmer, so please excuse any dumbness of this question, how the following code is encapsulating private 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
它提供了一个封装:它说,“你可以获取和设置一个 Age 属性,但我不会告诉你我是如何实现它的。”
这不是很强的封装,但它确实将实现细节与公共 API 分开。无需更改公共 API,您就可以开始将年龄存储在其他地方 - 在两个
short
字段中、在某个服务中、作为long
字段的一部分或其他任何地方。您可以将日志记录到该属性中以查看其使用频率。您可以添加一个在年龄发生变化时触发的事件(这是 API 更改,但不会破坏现有的调用者)。编辑:需要注意的一件事:即使现在什么也不做,对 make 它稍后做一些事情的更改是源代码和二进制兼容的。将字段更改为属性不向后兼容,无论是源代码形式还是二进制形式。在大多数情况下,它将是源代码兼容的,但不是二进制兼容的。在某些情况下,源将不再构建。在更邪恶的情况下(诚然,是做作的),两个版本都会构建,但效果不同。
另请注意,从 C# 3 开始,您可以像字段一样轻松地声明一个简单的属性:
我有一个 关于这一切的文章提供了更多详细信息。
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 along
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:
I have an article about all of this which provides more details.
这是一个有点空洞的例子。正如您所正确指出的,该属性似乎没有做任何事情。
但它可以。例如,SomeClass 可以对 Age 属性的修改方式施加限制(比如不将年龄更改为 -2 或 823 等错误值)。此外,SomeClass 内部不需要将age 表示为int。年龄可以是计算的结果(例如从一个人的出生日期中减去今天的日期),也可以作为另一种数据类型(例如字节、长整型或双精度型)存储在 SomeClass 中。
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).
并不是你在属性中实现了验证逻辑,或者没有实现,这里的封装意味着任何人都无法直接访问/修改您的私人数据。唯一可用的通道是穿过酒店。
使用底层代码,任何人都可以生成异常并造成各种破坏,因为他们可以对您的数据做任何他们想做的事情。
使用编写的顶部代码会造成同样的破坏,但在将来的任何时候,您都可以在属性中实现限制逻辑,而不必为此类的用户修改 API。
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.
它封装或包装了对私有变量
age
的更改。私有变量Age
不能由外部调用者直接修改,只能通过给定的public
方法修改。它正在设置一个界面,以便将来对age
的更改不会影响调用者。好处是将来有利于外部调用者,这就是为什么现在很难看到。It's encapsulating, or wrapping, changes to the private variable
age
. Private variableAge
can't be modified by external callers directly, only through thepublic
methods given. It's setting up an interface so future changes toage
won't break callers. The benefit is to external callers in the future, which is why it's hard to see now.在第一个示例中,SomeClass.Age 是一个属性。 “支持”该财产的字段是私有的。在第二个示例中,SomeClass.age 是公共字段。虽然在许多情况下可能没有区别,但选择属性而不是字段使您能够在不更改 API 或类的“形状”的情况下更改实现。也许您想要在属性更改时执行某些操作(坚持或通知)——这对于字段来说是不可能的。
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.
否(至少是您编写的特定代码)。
2 段代码几乎相同。与第二个相比,第一个没有提供任何有用的差异(如代码所写)。
使用 getter 和 setter 时,您可以限制对私有变量的访问。这可能是封装的一种形式。
IE
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.