使用getter和setter(只获取和设置)而不是简单地为这些变量使用公共字段有什么好处?

如果getter和setter所做的不仅仅是简单的get/set,我可以很快地解决这个问题,但我不是100%清楚如何做到:

public String foo;

比:

private String foo;
public void setFoo(String foo) { this.foo = foo; }
public String getFoo() { return foo; }

而前者需要的样板代码要少得多。


当前回答

另一个用途(在支持财产的语言中)是setter和getter可以暗示操作是非平凡的。通常,您希望避免在属性中执行任何计算成本高昂的操作。

其他回答

到目前为止,我在回答中遗漏了一个方面,即访问规范:

对于成员,设置和获取只有一个访问规范对于setter和getter,您可以对其进行微调并单独定义

此外,这是为了“未来证明”你的课程。特别是,从字段更改为属性是ABI中断,因此如果您稍后决定需要更多的逻辑而不仅仅是“设置/获取字段”,那么您需要中断ABI,这当然会给针对您的类编译的任何其他内容带来问题。

虽然getter和setter不常用,但这些方法的使用也可以用于AOP/代理模式的使用。例如,对于审计变量,您可以使用AOP来审计任何值的更新。没有getter/setter,除了到处更改代码外,其他都是不可能的。我个人从未使用过AOP,但它显示了使用getter/setter的另一个优势。

编辑:我回答这个问题是因为有很多学习编程的人都在问这个问题,大多数答案在技术上都很好,但如果你是新手,就不那么容易理解了。我们都是新手,所以我想我会尝试一个更适合新手的答案。

两个主要的是多态性和验证。即使它只是一个愚蠢的数据结构。

假设我们有一个简单的类:

public class Bottle {
  public int amountOfWaterMl;
  public int capacityMl;
}

这是一个非常简单的类,它包含有多少液体,容量是多少(毫升)。

当我这样做时会发生什么:

Bottle bot = new Bottle();
bot.amountOfWaterMl = 1500;
bot.capacityMl = 1000;

嗯,你不会指望这会奏效,对吧?你想进行某种理智检查。更糟糕的是,如果我从未指定最大容量呢?哦,亲爱的,我们有问题。

但也有另一个问题。如果瓶子只是一种容器呢?如果我们有几个容器,所有容器都有容量和液体量,会怎么样?如果我们能做一个接口,我们就可以让程序的其他部分接受这个接口,而瓶子、偷工减料和各种各样的东西就可以互换使用了。那不是更好吗?由于接口需要方法,这也是一件好事。

我们最终会得到这样的结果:

public interface LiquidContainer {
  public int getAmountMl();
  public void setAmountMl(int amountMl);
  public int getCapacityMl();
}

太棒了现在我们把瓶子换成这个:

public class Bottle extends LiquidContainer {
  private int capacityMl;
  private int amountFilledMl;

  public Bottle(int capacityMl, int amountFilledMl) {
    this.capacityMl = capacityMl;
    this.amountFilledMl = amountFilledMl;
    checkNotOverFlow();
  }

  public int getAmountMl() {
    return amountFilledMl;
  }

  public void setAmountMl(int amountMl) {
     this.amountFilled = amountMl;
     checkNotOverFlow();
  }
  public int getCapacityMl() {
    return capacityMl;
  }

  private void checkNotOverFlow() {
    if(amountOfWaterMl > capacityMl) {
      throw new BottleOverflowException();
    }
}

我将把BottleOverflowException的定义作为练习留给读者。

现在请注意这是多么的强大。我们现在可以通过接受LiquidContainer而不是Bottle来处理代码中的任何类型的容器。这些瓶子是如何处理这种东西的呢。您可以有在磁盘发生变化时将其状态写入磁盘的瓶子,也可以有保存在SQL数据库或GNU知道其他内容的瓶子。

所有这些都可以有不同的方法来处理各种各样的百日咳。瓶子只是检查,如果它溢出,就会抛出RuntimeException。但这可能是错误的做法。(关于错误处理有一个很有用的讨论,但我有意保持非常简单。评论中的人可能会指出这种简单方法的缺点。;)

是的,我们似乎从一个非常简单的想法迅速得到更好的答案。

请注意,您不能更改瓶子的容量。它现在被镶嵌在石头上。您可以通过将int声明为final来实现这一点。但如果这是一个列表,你可以清空它,添加新的东西,等等。你不能限制接触内脏的权限。

还有第三件事不是每个人都解决过:getter和setter使用方法调用。这意味着它们看起来像其他地方的正常方法。DTO和其他东西没有奇怪的特定语法,而是到处都有相同的语法。

来自数据隐藏的获取者和设置者。数据隐藏意味着我们正在向外部人员或外部人员/事物隐藏无法访问的数据这是OOP中一个有用的特性。

例如:

如果您创建了一个公共变量,您可以访问该变量并在任何地方(任何类)更改值。但如果创建为私有,则该变量无法在除声明的类之外的任何类中查看/访问。

public和private是访问修饰符。

那么我们如何在外部访问该变量:

这是获得者和获得者的地方。您可以将变量声明为private,然后可以为该变量实现getter和setter。

示例(Java):

private String name;

public String getName(){
   return this.name;
}

public void setName(String name){
   this.name= name;
}

优势:

当任何人想要访问或更改/设置平衡变量的值时,他/她必须获得许可。

//assume we have person1 object
//to give permission to check balance
person1.getName()

//to give permission to set balance
person1.setName()

您也可以在构造函数中设置值,但稍后需要时要更新/更改值,必须实现setter方法。