2013-01-18 43 views
29

我正在做一个大型项目的第一次。我有很多类,其中一些具有公共变量,一些具有setter和getter方法的私有变量,并且它们都具有这两种类型。我应该使用公有还是私有变量?

我决定重写这段代码主要只使用一种类型。但我不知道应该使用哪个变量(仅用于同一对象中的方法的变量始终是私有的,不是此问题的主题)。

我知道理论是什么公共和私人手段,但什么是在现实世界中使用,为什么?

+0

OO的答案是使用私有变量。但C++中的可见性模型非常糟糕(C++ 11中的可见性模型有点不那么明显),如果您不给它们命名的话,私有成员可能会导致非常令人惊讶的问题。 –

+8

@MarcGlisse Wut? – Collin

+0

近一个确切的重复数据删除:http://stackoverflow.com/questions/1596432/getter-and-setter-pointers-or-references-and-good-syntax-to-use-in-c –

回答

30

private数据成员通常被认为是好的,因为它们提供封装。

为它们提供的getter和setter打破封装,但它仍然比public数据成员更好,因为只有一次数据访问点。

在调试过程中您会注意到这一点。如果它是私人的,你知道你只能修改类中的变量。如果它是公开的,则必须搜索整个代码库,以便修改它的位置可能会修改

尽可能地禁止获得者/制定者并使属性private。这遵循信息隐藏的原则 - 你不应该关心一个类的属性。它应该是独立的。当然,在实践中这是不可行的,如果是这样,那么一个设计会比没有的设计更加混乱和难以维护。

这当然是一个经验法则 - 比如,我只是用一个struct(相当于一个class公共访问),比如说,一个简单的点类:

struct Point2D 
{ 
    double x; 
    double y; 
}; 
+0

我会说setter/getter创建一个额外的访问点,除了直接访问变量。 – sth

+0

@sth但直接访问仅限于该类,所以它是一些东西。 (如果这就是你的意思,比是的) –

+3

+1“尽可能的禁止获得者/安装者。”我总是声称制定者是邪恶的(功能,我的意思是,我不介意那些狗)。 – Angew

0

公共变量通常气馁,更好的方式是让所有私有变量,并用getter和setter方法访问它们:

private int var; 

public int getVar() { 
    return var; 
} 

public void setVar(int _var) { 
    var = _var; 
} 

现代IDE像Eclipse和别人帮你提供类似功能,这样做“实现getter和二传手s“和”封装字段“(用相应的getter和setter调用替换所有直接的变量访问)。

+5

为什么将变量私人化并提供getter和setter更好?调用该过程“封装字段”是误导性的;它只是用一种更详细的访问语法替换访问的一种语法。 (注意,问题被标记为C++。) –

+4

getters和setters提供了一种错误的封装感。 –

5

关于什么应该是私人/公共或保护没有硬性规定。

这取决于你的班级的作用和它提供的。

  • 所有这一切构成了 类内部工作的方法和成员应作出私人
  • 一个班级提供给外界的一切应该是public
  • 可能需要扩展的此类专业的成员和方法, 可能会被声明为受保护的
15

既然你说你知道理论和其他答案已经挖掘到公/私,getters和setters的含义,我想关注为什么要使用访问器而不是创建公共属性(C++中的成员数据)。

试想一下,你在一个物流项目一类车:

class Truck { 
public: 
    double capacity; 

    // lots of more things... 
}; 

前提是你northamerican,你可能会为了表示你的卡车的容量使用加仑。想象一下,你的项目已经完成,它完美的工作,尽管许多直接使用Truck::capacity完成。事实上,你的项目成功了,所以一些欧洲公司要求你调整你的项目给他们;不幸的是,该项目现在应该使用公制系统,因此应该使用公升而不是加仑的容量。

现在,这可能是一团糟。当然,一种可能性是仅为北美准备一个代码库,并且仅为欧洲准备一个代码库。但这意味着错误修复应该应用在两个不同的代码源中,并且这被认为是不可行的。

解决方案是在您的项目中创建配置可能性。用户应该能够设置加仑或升,而不是固定的硬连线选择。

以上述方法,这将意味着很多工作,您将不得不追踪Truck::capacity的所有用途,并决定如何处理它们。这可能意味着要修改整个代码库中的文件。让我们假设,作为一种选择,你决定采用更多的方法。

class Truck { 
public: 
    double getCapacity() const 
     { return capacity; } 

    // lots of more things... 
private: 
    double capacity; 
}; 

一个可能的替代改变不涉及修改类的接口:

class Truck { 
public: 
    double getCapacity() const 
     { if (Configuration::Measure == Gallons) { 
      return capacity; 
      } else { 
      return (capacity * 3.78); 
      } 
     } 


    // lots of more things... 
private: 
    double capacity; 
}; 

(请带参数帐户有很多这样做的方式,一个是只有一种可能,而这仅仅是一个例子)

你必须创建全球公用事业类配置(但你不得不这样做也无妨),并添加truck.hconfiguration.h的包括但这些都是局部的变化,留您的代码库保持不变,从而避免潜在的错误。

最后,你还声明你现在正在一个大项目中工作,我认为这是这些理由实际上更有意义的领域。请记住,在大型项目中工作时要牢记的目标是创建可维护的代码,即可以使用新功能纠正和扩展的代码。你可以忘记个人,小型项目中的获得者和制定者,尽管我试图让自己习惯于他们。

希望这会有所帮助。

+1

我知道这是一个玩具的例子,我大多同意结论,但请,如果你正在运行一个项目包括多个单位,**不这样做**。 相反,在内部使用SI单元存储所有内容,并且只在与用户交互时在单元之间进行转换(在视图层中,如果您正在远程执行某项操作)。 – Nax

2

有一些数据类型的唯一目的是保存指定的数据。这些通常可以用公共数据成员编写为结构。除此之外,一个类应该定义一个抽象。公共变量或微不足道的设置者和获取者表明,设计没有得到充分的思考,导致抽象概念不集中,不抽象。不要考虑数据,请考虑行为:该类应该执行X,Y和Z.从那里决定需要哪些内部数据来支持所需的行为。起初这并不容易,但请不断提醒自己,重要的是行为,而不是数据。

3

从OOP的角度来看,getters/setters有助于封装,因此应始终使用。当你调用一个getter/setter时,这个类可以在幕后做任何事情,并且这个类的内部不会暴露在外面。

。另一方面,从一个C++点,它也可能是一个缺点,如果类确实很多意想不到的事情,当你只是想获取/设置的值。人们喜欢知道某些访问是否会导致巨大的开销或简单高效。当你访问一个公共变量时,你确切地知道你得到了什么,当你使用getter/setter时,你不知道。

特别是如果你只是做一个小项目,花费时间写getter/setter方法并调整它们都相应地,当你决定改变你的变量名/型号/ ...产生大量无用功的而收效甚微。你最好花时间编写一些有用的代码。

C++代码通常不使用getter/setter方法时,他们不提供真正的收获。如果你设计了一个具有许多模块的1,000,000行项目,这些模块必须尽可能独立,这可能是有道理的,但是对于你每天编写的大多数正常大小的代码来说,这些代码是过度的。

0

私有成员变量优于公众成员变量,主要是针对上述(封装,以及规定的数据等。)所述的理由。它们也提供了一些数据保护,因为它保证了如果需要的话,没有通过setter的正确渠道,外部实体不能改变成员变量。

getter和setter的另一个好处是,如果你使用的是IDE(如Eclipse和Netbeans的),你可以使用IDE的功能,在该功能被称为代码库搜索地方。它们提供了关于该特定类中的一段数据正在被使用或修改的可见性。此外,通过创建内部互斥锁,您可以轻松地访问成员变量线程。 getter/setter函数会在访问或修改变量之前获取此互斥锁。

我是抽象的支持者到它仍然是有用的地步。为了抽象化抽象通常导致混乱的混乱,比它的价值更复杂。

相关问题