我是第一次做大项目。我有很多类,其中一些有公共变量,一些有setter和getter方法的私有变量,同样有两种类型。
我决定重写此代码,主要只使用一种类型。但我不知道应该使用哪个(仅用于同一对象中的方法的变量始终是私有的,不受此问题的影响)。
我知道公共和私人意味着什么,但在现实世界中使用什么以及为什么?
答案 0 :(得分:33)
private
数据成员通常被认为是好的,因为它们提供了封装。
为他们提供getter和setter打破了封装,但它仍然比public
数据成员更好,因为只有一次访问该数据的访问点。
你会在调试过程中注意到这一点。如果它是私有的,你知道你只能修改类中的变量。如果它是公开的,您将必须在整个代码库中搜索可能被修改的位置。
尽可能禁止getter / setter并制作属性private
。这遵循信息隐藏的原则 - 您不应该关心类具有什么属性。它应该是独立的。当然,在实践中这是不可行的,如果是这样的话,那么遵循这一设计的设计将比没有设计的设计更加混乱和难以维护。
这当然是一个经验法则 - 例如,我只使用struct
(相当于class
具有公共访问权限),例如,一个简单的点类:
struct Point2D
{
double x;
double y;
};
答案 1 :(得分:16)
既然你说你知道这个理论,并且其他答案已经挖掘了公共/私人,吸气者和制定者的意义,我想集中讨论使用访问者而不是创建公共属性的原因(成员数据)在C ++)。
想象一下,你在后勤项目中有一个类卡车:
class Truck {
public:
double capacity;
// lots of more things...
};
如果您是北美人,您可能会使用加仑来代表卡车的容量。想象一下,您的项目已经完成,它完美运行,但Truck::capacity
的许多直接用途都已完成。实际上,您的项目取得了成功,因此一些欧洲公司要求您调整您的项目;不幸的是,该项目现在应该使用公制系统,因此应该使用升而不是加仑。
现在,这可能是一团糟。当然,一种可能性是仅为北美准备代码库,而仅为欧洲准备代码库。但这意味着错误修复应该应用于两个不同的代码源,并且这决定是不可行的。
解决方案是在项目中创建配置可能性。用户应该能够设置加仑或升,而不是固定的,硬连线的加仑选择。
通过上面所述的方法,这将意味着很多工作,您将不得不追踪Truck::capacity
的所有用途,并决定如何处理它们。这可能意味着修改整个代码库中的文件。作为替代方案,我们假设你决定采用更多的theoretic
方法。
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.h
中为configuration.h
添加包含,但这些都是本地更改,其余您的代码库保持不变,从而避免潜在的错误。
最后,你还说你现在正在一个大项目中工作,我认为这是一个实际上更有意义的领域。请记住,在大型项目中工作时要记住的目标是创建可维护的代码,即可以使用新功能进行更正和扩展的代码。你可以忘记个人小项目中的getter和setter,尽管我会让自己习惯他们。
希望这有帮助。
答案 2 :(得分:5)
对于私人/公共或受保护的内容,没有严格的规定。
这取决于你班级的作用及其提供的内容。
答案 3 :(得分:3)
从OOP的角度来看,getters / setters有助于封装,因此应始终使用。当你调用getter / setter时,类可以在幕后做任何想做的事情,并且类的内部不会暴露在外面。
另一方面,从C ++的角度来看,当你想要获取/设置一个值时,如果类会做很多意想不到的事情,那么它也会是一个缺点。人们喜欢知道某些访问是否会导致巨大的开销或简单而有效。当您访问公共变量时,您确切知道自己得到了什么,当您使用getter / setter时,您根本不知道。
特别是如果你只做一个小项目,花时间编写getter / setter并相应地调整它们,当你决定改变你的变量名称/类型/ ...时会产生大量的繁忙工作而收效甚微。你最好花时间编写一些有用的代码。
C ++代码在不提供实际收益时通常不使用getter / setter。如果你设计一个1,000,000行的项目,其中包含许多必须尽可能独立的模块,那么它可能是有意义的,但是对于大多数正常大小的代码,你每天都在编写它们是有点过分的。
答案 4 :(得分:2)
有些数据类型的唯一目的是保存指定数据的数据。这些通常可以写为具有公共数据成员的结构。除此之外,一个类应该定义一个抽象。公共变量或琐碎的setter和getter表明设计没有被充分考虑,导致弱抽象的聚集,这些抽象不抽象任何东西。考虑行为,而不考虑数据:此类应该执行X,Y和Z.从那里,确定需要哪些内部数据来支持所需的行为。这一开始并不容易,但要不断提醒自己重要的是行为,而不是数据。
答案 5 :(得分:1)
私有成员变量优先于公共成员变量,主要是出于上述原因(封装,明确指定的数据等)。它们还提供了一些数据保护,因为它保证了在没有通过设置器的适当通道的情况下,如果需要,任何外部实体都不能改变成员变量。
getter和setter的另一个好处是,如果您使用的是IDE(如Eclipse或Netbeans),您可以使用IDE的功能在代码库中搜索函数所在的每个位置。它们提供了关于使用或修改该特定类中的数据的可见性的可见性。此外,通过使用内部互斥锁,您可以轻松地访问成员变量线程安全。 getter / setter函数会在访问或修改变量之前获取此互斥锁。
我是抽象的支持者,它仍然有用。为抽象而抽象通常会导致混乱,比其价值更复杂。
答案 6 :(得分:0)
通常不鼓励使用公共变量,更好的形式是将所有变量设为私有并使用getter和setter访问它们:
private int var;
public int getVar() {
return var;
}
public void setVar(int _var) {
var = _var;
}
像Eclipse和其他现代IDE一样,通过提供诸如“实现Getters和Setters”和“Encapsulate Field”(用相应的getter和setter调用替换所有变量的直接访问)等功能来帮助您实现这一目标。