封装在哪里?

时间:2010-09-16 15:10:44

标签: properties field 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;
    }
}

第一个代码是否提供任何封装?

6 个答案:

答案 0 :(得分:8)

它提供了一个封装:它说,“你可以获取和设置Age属性,但我不会告诉你我是如何实现它的。”

这不是非常强大的封装,但它确实将实现细节与公共API分开。在根本不更改公共API的情况下,您可以开始将年龄存储在其他地方 - 在两个short字段中,在某个地方的服务中,作为long字段的一部分或其他任何内容。您可以在该属性中记录日志以查看它的使用频率。你可以添加一个在年龄变化时被触发的事件(这是一个API更改,但不会破坏现有的调用者)。

编辑:有一点需要注意:即使现在什么也没做,但是 make 之后做的更改是源和二进制兼容的。将字段更改为属性向后兼容,无论是源格式还是二进制格式。在大多数情况下,它将与源代码兼容,但不兼容二进制。在某些情况下,源将不再构建。在更邪恶(并且设想,不可否认)两个版本将构建,但具有不同的效果。

另请注意,从C#3开始,您可以像字段一样轻松地声明一个简单的属性:

public int Age { get; set; }

我有一个article about all of this,提供了更多详细信息。

答案 1 :(得分:2)

这是一个空洞的例子。正如您所正确指出的那样,该物业似乎没有做任何事情。

但它可以。例如,SomeClass可以限制Age属性的修改方式(例如,不要将年龄改为-2或823之类的错误值)。此外,SomeClass不需要在内部将age表示为int。年龄可能是计算的结果(比如说从一个人的出生日期减去今天的日期),或者它可以作为另一种数据类型(比如一个字节,长或双)存储在SomeClass中。

答案 2 :(得分:2)

  

我的意思是,在属性中没有限制逻辑或过滤逻辑,上面的内容与下面的内容有什么不同

这不是你已经或者没有在属性中实现验证逻辑的事实,这里的封装意味着没有人可以直接访问/修改你的私人数据。唯一可用的通道是通过酒店。

使用底部代码,任何人都可以产生异常并造成各种破坏,因为他们可以对数据做任何他们想做的事情。

使用顶部代码作为其编写允许同样的破坏,但在将来的任何时候您都可以在属性中实现限制逻辑,而不必为此类的用户修改API。

答案 3 :(得分:1)

它封装或包装对私有变量age的更改。私有变量Age不能由外部呼叫者直接修改,只能通过给定的public方法修改。它正在设置一个界面,因此将来age的更改不会破坏呼叫者。对未来的外部呼叫者有利,这就是现在很难看到的原因。

答案 4 :(得分:0)

在您的第一个示例中,SomeClass.Age是一个属性。 “支持”该财产的字段是私有的。在第二个示例中,SomeClass.age是一个公共字段。虽然在许多情况下可能没有区别,但在字段上选择属性使您能够在不更改API或类的“形状”的情况下更改实现。也许你想在财产发生变化时做某事(坚持或通知) - 这对于一个领域是不可能的。

答案 5 :(得分:0)

  

第一个代码是否提供任何封装?

否(至少你写的特定代码)。

这两段代码几乎相同。与第二个相比,第一个没有提供任何有用的差异(如编写代码)。

使用getter和setter时,可以限制访问私有变量。这可能是封装的一种形式。

private int x

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