获取器和设置器是如何工作的?

112

我来自php世界。你能解释一下什么是getter和setter,还能举几个例子吗?


@yegor256 我理解你的狗和球的比喻,甚至支持它,但是如果一个“生物体”对象存储偶尔的原始值,例如ID,该怎么办?如果您想超越简单的赋值,但又不想编写新类来处理原始值,该怎么办? - Jacksonkr
6个回答

129

不一定需要教程。可以阅读关于封装的知识。

private String myField; //"private" means access to this is restricted to the class.

public String getMyField()
{
     //include validation, logic, logging or whatever you like here
    return this.myField;
}
public void setMyField(String value)
{
     //include more logic
     this.myField = value;
}

11
Getter就是一个获取私有字段的方法,而Setter则是设置新字段的方法。感谢代码提供的出色解释。 - ajsie
1
你能给一个 getter 传递参数吗? - ajsie
2
noname:不是,也不行。Getter 是获取值的方式,但不会暴露字段中包含的值,也就是说,如果您调用 someObj.getTime().setHour(5),它不应该影响 someObj 的内部状态。另外,getter 和 setter(也称为访问器和变异器)具有非常严格的方法签名,这意味着 getter 没有任何参数。总之,方法通常只应该做一件事情。 - Esko
4
当简单的事物被赋予复杂/大量/抽象的名称时,就会形成所谓的“设计模式”...这是我刚刚发明的递归概念解释模式的一个例子;-) - namespaceform
3
除非出现更具体范围的冲突,否则“this”关键字是可选的。在您提供的示例中,创建的setter将具有一个参数,其名称与字段名称匹配,因此使用“this.fieldName = fieldName”可区分是对字段进行赋值而不是对参数自身进行赋值,例如“fieldName = fieldname”就可以达到这个目的。在getter中不存在这样的冲突。 - Paul Creasey
显示剩余5条评论

39

在Java中,getter和setter是普通的函数。唯一将它们归类为getter或setter的是惯例。foo属性的getter称为getFoo,setter称为setFoo。对于布尔值,getter称为isFoo。它们还必须具有特定的声明方式,如下所示的'name'属性的getter和setter示例:

class Dummy
{
    private String name;

    public Dummy() {}

    public Dummy(String name) {
        this.name = name;
    }

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

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

使用 getter 和 setter 而不是将成员变量公开的原因在于,这样可以在不改变接口的情况下更改实现方式。此外,许多使用反射来检查对象的工具和工具包只接受具有 getter 和 setter 的对象。JavaBeans 例如必须具有 getter 和 setter,以及其他一些要求。


9
这些构造函数不应该有'void'吗? - Jason Hartley
这里实际上需要使用Void。如果没有它,你会得到以下错误:error: invalid method declaration; return type required - Dan
3
这里不需要使用"Void". - Shashi Kiran
2
@JasonHartley:构造函数没有返回类型。 - wassimans
@Mark Byers,因此构造函数用于初始化实例,而setter用于更改任何给定属性。这正确吗? - carloswm85

12
class Clock {  
        String time;  

        void setTime (String t) {  
           time = t;  
        }  

        String getTime() {  
           return time;  
        }  
}  


class ClockTestDrive {  
   public static void main (String [] args) {  
   Clock c = new Clock;  

   c.setTime("12345")  
   String tod = c.getTime();  
   System.out.println(time: " + tod);  
 }
}  

当您运行程序时,程序从main函数开始执行。
1. 创建对象c。 2. 对象c调用函数setTime()。 3. 变量time被设置为传递的值。 4. 对象c调用函数getTime()。 5. 时间被返回。 6. 它将传递给tod,然后tod被打印出来。

10

您可能还想阅读 "为什么getter和setter方法是有害的":

虽然在Java中,getter/setter方法很常见,但它们并不特别面向对象(OO)。实际上,它们可能会损害代码的可维护性。此外,大量的getter和setter方法的存在表明该程序从OO角度来看并不一定设计良好。

本文解释了为什么您不应该使用getter和setter(以及何时可以使用它们),并建议一种设计方法论,可以帮助您摆脱getter/setter思维方式。


3

1. 最好的获取器/设置器是智能的。

这里有一个来自 Mozilla 的 JavaScript 示例:

var o = { a:0 } // `o` is now a basic object

Object.defineProperty(o, "b", { 
    get: function () { 
        return this.a + 1; 
    } 
});

console.log(o.b) // Runs the getter, which yields a + 1 (which is 1)

我非常喜欢使用这些,因为它们非常棒。当我进行编程和动画时,我会使用它。例如,创建一个处理Number并在您的网页上显示该数字的setter。当使用setter时,它会使用tweener将旧数字动画到新数字。如果初始数字为0,并将其设置为10,则您将在半秒钟内看到数字从0快速翻转到10。用户喜欢这种东西,而且创造它很有趣。

2. PHP中的getter/setter

来自sof的示例

<?php
class MyClass {
  private $firstField;
  private $secondField;

  public function __get($property) {
    if (property_exists($this, $property)) {
      return $this->$property;
    }
  }

  public function __set($property, $value) {
    if (property_exists($this, $property)) {
      $this->$property = $value;
    }

    return $this;
  }
}
?>

引用:


2

这里有一个例子,解释了在Java中使用getter和setter的最简单方法。你可以用更直接的方式来做这件事,但是getter和setter有一些特殊的地方,就是当在继承中的子类中使用父类的私有成员时。通过使用getter和setter,你可以使其成为可能。

package stackoverflow;

    public class StackoverFlow 

    {

        private int x;

        public int getX()
        {
            return x;
        }

        public int setX(int x)
        {
          return  this.x = x;
        }
         public void showX()
         {
             System.out.println("value of x  "+x);
         }


        public static void main(String[] args) {

            StackoverFlow sto = new StackoverFlow();
            sto.setX(10);
            sto.getX();
            sto.showX();
        }

    }

我不会给你点踩(不值得那个努力)。请注意:(1)你回答的是一个Java问题,程序语言应该是Java。(2)如果你想发帖,请确保布局正确。(3)你对封装(getter(或访问器)和setter(或变异器))的使用是错误的。请查阅封装的含义...(查看被投票的答案) - KarelG
1
@KarelG 对不起,我没有看标签。我已经更新为Java了。谢谢你提醒我。 - Bashir ahmad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接