为什么java需要封装,关于java:封装 – 当setter已经公开时我们为什么需要它?...

本问题已经有最佳答案,请猛点这里访问。

封装是隐藏数据。 我想在这里听到一些非常有趣的答案。

当我们已经为变量声明public setter方法时,将变量保持为private的原因是什么?

我理解封装的用法但是当我们将setter作为public时,将变量保持为private的重点是什么,我们可以直接使用public访问修饰符

是因为我们不希望其他人知道我们在后端存储数据或管理数据的确切方式吗?

这可以被认为是相反的问题。

我有大型系统,有数十万或数百万行代码,没有一个setter。 我喜欢这样。

@ McAdam331是的,它是..提问者提到了java但是它是使用getter和setter的所有语言的应用程序。 这是一个与oop相关的方面..谢谢:)

因为您可以在setter中选择要公开的内容。

这是另一种看待它的方式:cspray.net/programming/2012/05/13/

Is it because we do not want others to know the exact way we are

storing data or managing data on the back-end?

是的,这就是重点。它也与抽象和信息隐藏的概念有关。

您提供了一个公共setter,当由类客户端调用时,它将具有您已记录的效果。客户的业务如何实现这种效果并非如此。你在修改其中一个类属性吗?好吧,让客户知道,但不是你实际修改变量的事实。在将来,您可能希望修改您的类,以便它使用完全不同的东西(属性字典?外部服务?随便!)而不是简单的备份变量,而客户端不会破坏。

所以你的setter是一个抽象,你提供给客户端"修改这个类属性"。与此同时,您隐藏了使用内部变量的事实,因为客户端不需要知道这一事实。

(注意:这里我使用"属性"这个词作为通用概念,与任何具体的编程语言无关)

抽象就是隐藏功能。这是隐藏后端机制的一些方式,我们设置数据的方式..很好的解释...... :)

抽象是关于隐藏实现而不是功能。

功能取决于实现..所以是的,它回到了同样的事情..

但是,有(许多?)编程语言允许创建setter / getter属性,因此它们看起来像变量访问,但实际上是方法调用。访问的语法是相同的。因此,在这些语言中,如果您只关心能够修改类以使用不同的内部表示,那么您根本不需要隐藏任何内容。

开始使用公共setter而不是改变私有变量的另一个原因可能是,在某些时候你可能想要"警告"所设置的值。

我完全同意Konamiman的回答,但我想补充一点:

有些情况下你真的不想要这种抽象。那没关系。

我想在这里使用的一个简单示例是一个三维浮点向量的类:

class Vector3f {

public:

float x;

float y;

float z;

};

你可以将这些字段设为私有并提供安装者吗?当然,你可以。但是在这里你可能会争辩说,这个类实际上只是提供了一个浮点元组,你不需要任何额外的功能。因此,添加setter只会使类复杂化,而您宁愿将字段保留为public。

现在,您可以轻松构建可能会在以后咬你的场景。例如,您可能有一天会要求Vector3f不允许存储NaN,并且如果有人试图这样做,则应该抛出异常。但是这样一个假设的未来问题不足以证明引入额外的抽象是合理的。

作为程序员,您可以决定哪些抽象对于手头的问题有意义,哪些抽象只会妨碍您完成工作。不必要的抽象是过度工程化的,会影响你的工作效率,就像不抽象一样。

一句话:不要因为有人声称这是一个好习惯而盲目地使用setter。相反,考虑手头的问题并考虑权衡。

好的,就是我说的,取决于你实际需要什么。

获得正确的平衡(在抽象过度和抽象不足之间)可能很困难。在任何一个方向上弄错都会损害生产力。

更相关的情况IMHO可能是如果Vector提供SetLocation函数,则向量的导数可能能够在其位置改变时触发某些动作。例如,MoveReportingVector可能在其构造函数中接受MotionReporter [接口]对象,并在MoveReportingVector上调用SetLocation时调用其ReportMotion方法。我希望Java有办法声明非final字段是公开可读的,但可以在本地修改,以便于这些类型,因为这种语义通常是合适的。

因为通过封装,我们提供单点访问。假设您按如下方式定义变量及其setter

String username;

public void setUsername(String username){

this.username = username;

}

稍后您想在设置username属性之前添加一些验证。如果您通过直接访问该属性将用户名设置为10个位置,那么您没有单点访问权限,您需要在10个位置进行此更改。但是,如果您有一个setter方法,那么通过在一个地方进行更改,您可以轻松实现结果。

尽管Konamiman的答案很明显,但我想补充一点,在公共制定者的特殊情况下,与直接揭露你所要求的公共领域相比,除了信息隐藏和脱离实现之外,还有另一个非常重要的区别。类的公共表面或API;验证。

在公共字段方案中,无法在修改字段时验证字段的值。如果是公共setter(无论是Foo {get; set;}属性还是SetFoo(Foo value))方法,您可以添加验证代码并启动所需的副作用,这样可以确保您的类始终处于有效或可预测的状态。

想一想:我通过课堂代表一个真实的生活对象,一个狮子。我会做这样的事情。

class Lion {

public int legs;

}

现在我的类需要其他开发人员来创建一个对象并设置它的leg字段。他会做这样的事情

Lion jungleKing = new Lion();

jungleKing.legs=15;

现在问题是,Java不会限制他设置任何超过4的数字作为该对象的腿数。这不是一个错误,它会运行得很好。但这是一个逻辑错误,编译器不会帮助你。这样狮子可以有任意数量的腿。

但是如果我们以这种方式编写代码

class Lion {

private int legs;

public void setLegs(int legs){

if(legs>4)

this.legs=4;

else this.legs=legs;

}

}

现在你不会有任何超过4条腿的狮子,因为更新类的字段的策略已经由类本身定义,并且没有人不知道该策略将更新leg字段因为唯一的方法更新leg字段是通过setLegs()方法,该方法知道类的策略。

很好的答案,但最后一个时期可能会使用一些逗号。

如果您想在分配前进行范围检查,该怎么办?这是我使用setter和getter的案例之一

将字段设置为私有文档是一个强大的事实:这些私有字段仅直接在当前类中使用。这有助于维护人员不必追踪现场使用情况。他们可以通过查看类并确定类环境对这些字段的影响来自公共和受保护的方法调用,从而更好地对代码进行推理。它限制了课堂上的曝光表面。

反过来,为私人领域定义"设定者"并不是要再次宣传它。它是关于声明另一个强大的事实:属于这个类的对象有一个可以从外部修改的属性。 (术语对象和属性用于整体的有界部分和关于此部分的可观察事实,而不是在OOP意义上)

为什么在将字段设为公开时在字段上声明"setter"就足够了?因为声明字段不仅会将名称绑定到类的对象的属性,还会承诺为此属性使用内存存储。

因此,如果您声明"具有setter的私有字段",则声明三件事:

您声明您为字段/ setter集群指定的名称表示对象的属性,当对象被视为黑盒时,该属性是您感兴趣的。

您声明此属性的值可由对象的环境修改。

您声明在此特定的具体类中,通过向其提交一些内存存储来实现对象的属性。

我主张你永远不要让你的领域与getter和setter一起私密。字段用于描述存储。方法用于与环境交互。 ("getters"和"setter"的特殊情况用于描述感兴趣的属性)

维基百科对[mutator方法(https://en.wikipedia.org/wiki/Mutator_method)有很好的概述,这就是setter方法以及它们如何在不同语言中工作的方法。

简短版本:如果你想引入验证或其他在对象修改时执行的逻辑,那么有一个setter来放置那个逻辑是很好的。另外你可能想隐藏你存储的东西。因此,这些是获得/获得者的原因。同样,对于getter,您可能具有提供默认值或值的逻辑,这些默认值或值依赖于例如。 Locale,字符编码等等的配置。除了获取或设置实例变量之外,有许多有效的理由想要获得逻辑。

显然,如果你有getter和setteres,你不希望人们通过直接操作对象状态绕过它们,这就是你应该保持实例变量私有的原因。

其他需要考虑的事项包括你是否真的希望你的对象完全可变(如果没有,make field final),是否要修改对象状态线程安全,例如:锁,同步等

我在实践中遇到的或多或少简单而真实的例子是Options类,它有很多setter和getter。在某些时候,您可能希望添加取决于其他选项或具有副作用的新选项。甚至用Enum替换选项组。在这种情况下,setA函数不仅会修改a字段,还会隐藏一些额外的配置逻辑。类似地,getA不仅会返回a的值,而是config == cStuffSupportingA。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值