[英]Where's the Encapsulation?
我是一个新程序员,所以请原谅这个问题的愚蠢,以下代码是如何封装私有数据的? ——
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;
}
}
第一个代码是否提供任何封装?
它提供了一个封装:它说,“你可以获取和设置一个 Age 属性,但我不会告诉你我是如何实现它的。”
这不是很强的封装,但它确实将实现细节与公共 API 分开。 根本不更改公共 API,您可以开始将年龄存储在其他地方 - 在两个short
字段中,在某处的服务中,作为long
字段的一部分或其他任何地方。 您可以将日志记录在属性中以查看它的使用频率。 您可以添加一个在年龄变化时触发的事件(这是一个 API 变化,但不会破坏现有的调用者)。
编辑:需要注意的一件事:即使现在什么都不做,让它在以后做一些事情的改变是源代码和二进制兼容的。 将字段更改为属性不向后兼容,无论是源代码形式还是二进制形式。 在大多数情况下,它将是源代码兼容的,但不是二进制兼容的。 在某些情况下,源将不再构建。 在更邪恶的(和人为的,无可否认)中,两个版本都会构建,但具有不同的效果。
另请注意,从 C# 3 开始,您可以像声明字段一样轻松地声明一个平凡的属性:
public int Age { get; set; }
这是一个有点空洞的例子。 正如您正确指出的那样,该属性似乎没有做任何事情。
但它可以。 例如,SomeClass 可以限制 Age 属性的修改方式(比如不将年龄更改为 -2 或 823 之类的错误值)。 此外, SomeClass 不需要在内部将年龄表示为 int。 年龄可能是计算的结果(比如从一个人的出生日期减去今天的日期),或者它可以作为另一种数据类型(比如字节、长或双)存储在 SomeClass 中。
我的意思是,在属性中没有限制逻辑或过滤逻辑,上面的和下面的有什么不同
这不是你在属性中实现或没有实现验证逻辑的事实,这里的封装意味着没有人可以直接访问/修改你的私有数据。 唯一可用的方法是穿过酒店。
使用底层代码,任何人都可以产生异常并造成各种破坏,因为他们可以对您的数据做任何他们想做的事情。
使用编写的顶级代码会造成同样的破坏,但在未来的任何时候,您都可以在属性中实现限制逻辑,而不必为此类用户修改 API。
它封装或包装了对私有变量age
更改。 私有变量Age
不能被外部调用者直接修改,只能通过给定的public
方法进行修改。 它正在设置一个界面,因此未来对age
更改不会中断呼叫者。 好处是将来外部调用者,这就是为什么现在很难看到。
第一个代码是否提供任何封装?
否(至少是您编写的特定代码)。
两段代码几乎相同。 与第二个相比,第一个没有提供任何有用的差异(在编写代码时)。
使用 getter 和 setter 时,您可以限制对私有变量的访问。 这可能是封装的一种形式。
即
private int x
public int getInt(String password){
if(password == 'RealPassword'){
return x
}
}
在您的第一个示例中, SomeClass.Age 是一个属性。 “支持”该财产的字段是私有的。 在您的第二个示例中, SomeClass.age 是一个公共字段。 虽然在许多情况下可能没有区别,但在字段上选择属性使您能够在不更改 API 或类的“形状”的情况下更改实现。 也许你想在属性改变时做一些事情(坚持或通知)——这对一个字段是不可能的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.