私人与公众的务实观点

时间:2010-03-28 18:48:49

标签: private public

我一直想知道publicprotectedprivate属性的主题。当我 来破解别人的代码时,我的记忆很容易回想起,并且将被黑客攻击的类变量声明为private总是令人沮丧。

此外,还有(更多)时间我自己写了一个课程,并且从未认识到任何将房产私有化的潜在收益。我应该注意,在我的习惯中使用公共变量是而不是:我通过使用getter和setter来遵守OOP的原则。

那么,这些限制的重点是什么?

9 个答案:

答案 0 :(得分:7)

使用私有 public 称为封装。简单的洞察力是软件包(类或模块)需要内部和外部。

外面(公众)是你与世界其他地方的合约。你应该尽量保持简单,连贯,明显,万无一失,非常重要,稳定。

如果您对良好的软件设计感兴趣,那么规则就是:将所有数据设为私有,并在需要时公开方法。

隐藏数据的原则是类中所有字段的总和定义了对象 state 。对于编写良好的类,每个对象应该负责保持有效状态。如果该州的一部分是公开的,那么该班级永远不会给予这种保证。

一个小例子,假设我们有:

class MyDate
{ 
    public int y, m, d;
    public void AdvanceDays(int n) { ... } // complicated month/year overflow
    // other utility methods
};

您无法阻止该类用户忽略AdvanceDays(),只需执行以下操作:

date.d = date.d + 1; // next day

但是,如果您将y, m, d设为私有并测试所有MyDate方法,则可以保证系统中只有有效日期。

答案 1 :(得分:4)

重点是使用privateprotected来防止暴露类的内部细节,以便其他类只能访问您的类提供的公共“接口”。如果做得好,这可能是值得的。

我同意private可能是一个真正的痛苦,特别是如果你从库中扩展类。一段时间后,我不得不从Piccolo.NET框架扩展各种类,并且令人耳目一新,他们已经宣布我需要的所有内容protected而不是private,所以我能够扩展我需要的一切无需复制代码和/或修改库。一个重要的外卖课程是,如果您正在为库或其他“可重用”组件编写代码,那么在声明任何内容之前您应该三思而后行private

答案 2 :(得分:2)

关键字private不应该用于私有化您要公开的属性,而是用于保护您的类的内部代码。我发现它们非常有用,因为它们可以帮助您定义代码中必须隐藏的部分,以及每个人都可以访问的部分。

答案 3 :(得分:0)

我想到的一个例子是,在设置/获取私有成员的值之前,您需要进行某种调整或检查。因此,您将创建一个带有某些逻辑的公共setter / getter(检查某些内容是否为null或任何其他计算),而不是直接访问私有变量并始终必须在代码中处理该逻辑。它有助于代码合同和期望的内容。

另一个例子是辅助函数。您可能会将一些较大的逻辑分解为较小的函数,但这并不意味着您希望每个人都能看到并使用这些辅助函数,您只希望它们访问您的主API函数。

换句话说,您希望隐藏代码中的某些内部接口

查看有关API的视频,例如this Google talk

答案 4 :(得分:0)

最近我有从头开始设计和实现对象系统的极端奢侈,我采取了强制所有变量(相当于)protected的政策。我的目标是鼓励用户始终将变量视为实现的一部分,而不是规范。 OTOH,我也留下了钩子,允许代码打破这个限制,因为仍有理由不遵循它(例如,对象序列化引擎不能遵循规则)。

请注意,我的课程不需要强制执行安全性;该语言还有其他机制。

答案 5 :(得分:0)

在我看来,使用私有成员的最重要原因是隐藏实现,以便将来可以更改它而不会更改后代。

答案 6 :(得分:0)

某些语言 - 例如Smalltalk--根本没有可见性修饰符。

在Smalltalk的情况下,所有实例变量都是私有的,所有方法都是公共的。开发人员通过将方法置于“私有”协议中来指示方法的“私有” - 可能发生变化的东西,或者自身没有多大意义的辅助方法。

一个类的用户可以看到他们应该三思而行,发送一个标记为私有的消息给该类,但仍然可以自由地使用该方法。

(注意:Smalltalk中的“属性”只是getter和setter方法。)

答案 7 :(得分:0)

我个人很少使用受保护的成员。我通常赞成compositiondecorator patternstrategy pattern。在很少的情况下,我相信子类(程序员)正确处理受保护的变量。有时我有保护方法明确提供专门用于子类的接口,但这些情况实际上很少见。

大多数时候我有一个只有公共纯虚拟的absract基类(现在谈论C ++),实现类实现这些。有时他们会添加一些特殊的初始化方法或其他特定功能,但其余的都是私有的。

答案 8 :(得分:0)

首先,'属性'可以用不同语言引用不同的东西。例如,在Java中,您将意味着实例变量,而C#则区分两者。

我会假设你的意思是实例变量,因为你提到了getter / setter。

其他人提到的原因是封装。 Encapsulation给我们带来了什么?

灵活性

当事情必须改变时(他们通常会这样做),我们不太可能通过正确封装属性来破坏构建。

例如,我们可能决定进行如下更改:

int getFoo()
{
  return foo;
}

int getFoo()
{
  return bar + baz;
}

如果我们没有封装'foo'开头,那么我们需要更多的代码来改变。 (比这一行)

封装属性的另一个原因是提供一种防范代码的方法:

void setFoo(int val)
{
  if(foo < 0)
    throw MyException(); // or silently ignore

  foo = val;
}

这也很方便,因为我们可以在mutator中设置一个断点,这样我们就可以在某些东西试图修改我们的数据时中断。

如果我们的财产是公开的,那么我们就无法做到这一点!