2

我最近开始在 Java 中工作,并被介绍给一切事物的 getter 和 setter 的狂野而疯狂的世界。起初我讨厌它,但很快就习惯了。太习惯了。

最近我花了很多时间来更多地思考班级设计。我正在尝试做的一件事是避免为所有事情做 getter 和 setter 的陷阱。然而,我所做的大部分工作都是处理主要是数据容器的实体,我不确定在这些情况下 getter 和 setter 是否真的不合适。

这是一个使用公共属性的简单示例。

class Space {
    public String name;
    public String description;
    Space(final String name, final String description) {
        this.name = name;
        this.description = description;
    }
}

这是一个使用私有属性并使用 getter 和 setter 的简单示例。

class Space {
    private String name;
    private String description;
    Space(final String name, final String description) {
        this.name = name;
        this.description = description;
    }
    public String getName() {
        return this.name;
    }
    public void setName(final String name) {
        this.name = name;
    }
    public String getDescription() {
        return this.description;
    }
    public void setDescription(final String description) {
        this.description = description;
    }
}

在这些示例中, thenamedescription字段都应该可以更改。

我觉得 getter/setter 示例更清晰,并且隐藏了 whatnamedescriptionare 的实现细节。如果需要,它还允许稍后在片场进行验证。

我已经阅读了一些关于 getter 和 setter 是邪恶的和/或反模式的讨论,但感觉这些可能不适用于这种情况。

也许有一些我还没有考虑过的选择。我愿意接受建议!

4

4 回答 4

6

第一个版本(公共属性)不是一个好主意。第二个更好。正如 Josh Bloch 所说,“支持不变性”

public class Space {
    private final String name;
    private final String description;

    public Space(final String name, final String description) {
        this.name = name;
        this.description = description;
    }

    public String getName() {
        return name;
    }

    public String getDescription() {
        return description;
    }
}

话虽如此,getter 和 setter 往往被过度使用

于 2009-01-02T08:32:35.113 回答
4

您听说过经常过于简单化的“get/setter 是邪恶的”。没有人(我希望)真的意味着数据对象有什么问题。我认为真正的想法是:

“Getter/Setter 是邪恶的,除了普通的数据存储对象”,这本身就是“告诉不问”的福音。

理想情况下,如果一个类有 getter 和 setter,那就是它应该有的全部。

无论如何,这就是争论。我不确定我是否同意。

于 2009-01-02T09:06:23.580 回答
3

简单地说:

  • 对于必须从外部读取的所有字段,您都需要 getter。
  • 对于必须从外部写入的所有字段,您都需要设置器。

这可以是 100%,但大多数时候会更少。

于 2009-01-02T08:31:49.467 回答
0

虽然访问器模式有助于隐藏类的实现细节(例如,使用哈希表来存储属性以节省稀疏使用的类的内存),但实现起来可能非常冗长(您的示例有 12 行以上的访问器)。这就是为什么 C# 有一个特殊的属性语法,它允许简洁地指定默认访问器:

class Space {
    public String Name { get; set; }
    public String Description { get; set; }
    Space(final String name, final String description) {
        this.Name = name;
        this.Description = description;
    }
}

替代形式可以添加访问说明符和/或代码:

private String _name;
public String Name {
    get { if (_name == null) FetchName(); return _name; }
    private set { _name = value; }
}
于 2009-01-02T09:29:38.650 回答