繁体   English   中英

封装在哪里?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM