Setter 和 getter 的必要性

Posted

技术标签:

【中文标题】Setter 和 getter 的必要性【英文标题】:Setter and getter necessity 【发布时间】:2012-11-30 09:43:02 【问题描述】:

这是一个新手问题。在我简单的学习石头剪刀布游戏程序中,我有单个游戏实例类。游戏实例类有几个私有成员,如总回合数、获胜数、平局数等。这些类成员仅用于公共游戏实例的类方法,用于启动和处理游戏。我应该按照良好的代码风格为我的班级成员创建特殊的私有 getter 和 setter 方法吗?在游戏处理方法中直接与类成员一起工作会更好吗?

class GameInstance
    unsigned int m_totalTurns;
    unsigned int m_wins;
    unsigned int m_loses;
    unsigned int m_ties;
    int getWins() const;               // is it a bad idea?  
    int getLoses() const;              // is it a bad idea?  
    int getTotalTurns() const;         // is it a bad idea?  
    int getTies() const;               // is it a bad idea?  

    // some setters-like incrementing  // is it a bad idea?
    // same private members functions  // is it a bad idea?    
    // ....                            // is it a bad idea?  

    void finishGame();

public:
    explicit GameInstance():m_totalTurns(0), m_wins(0), m_loses(0), m_ties(0); 
    void startGame();
;

【问题讨论】:

【参考方案1】:

您可能会将 getter 公开,否则没有任何意义。

对于任何 getter 或 setter,它们都是类接口的一部分。如果您不想在外部允许直接获取这些成员或设置它们,请不要公开 getter 和 setter。

如果您希望使用addResult() 来指定获胜、平局或失败并在相关统计数据中添加一个,那么 getter 可能是一个想法,而 setter 看起来可能是个坏主意。

作为单个 getter 的替代方法,您可能有一个“getGameStats()”,它一次性返回所有 4 个。

如果您询问的是 getter 而不是提供公共访问权限(而不是根本不提供访问权限),那么对于具有方法的类,您通常应该将所有数据成员设为私有并使用 getter 以及必要时使用 setter。调试使用它们的代码也更容易,因为您可以在访问变量的点插入断点。

在“纯数据”结构中,您可以公开成员。事实上,在这种情况下,您可能有一个“GameStats”结构,您将从 getGameStats() 函数返回。 GameStats 本身只包含数字,您可以公开这些数字。但是,您的类中的 GameStats 实例应该是私有实例。

【讨论】:

谢谢,真的很有帮助。关于游戏统计结构,这是一个非常好的主意。【参考方案2】:

我认为这是一个很好的方法。它隐藏了实现。编辑起来更简单。假设您有 100 个使用 getTotalTurns() 的地方。一天之内,您需要更改 getter 的逻辑。而且您将需要更改一个位置而不是 100 个。不要考虑性能。编译器可能会内联所有这些函数。正如@CachCow 所说,没有真正的理由将它们设为私有(setters/getters)。您可以使它们受到保护以授予派生类的访问权限。但大多数时候 getter/setter 是供公众使用的。

【讨论】:

它不隐藏实现。你可以看到私人会员。它确实使您能够控制访问,并且从能够在出现问题时在 getter 中放置断点的角度来看更易于维护,而如果直接访问它,您将不知道在哪里放置断点. 我没有看到供私人使用的 getter/setter。那么是的,他们并不真正需要大多数变量。 getter 和 setter 有时可以受到保护以允许访问派生类(同时将其完全限制在外部)。但是,我认为将它们设为私有没有任何好处。【参考方案3】:

如果你有单线程项目,主界面和用户交互都在GameInstance类中,你在游戏过程中不需要访问这些字段。 游戏结束后,您可以通过 struct 将它们全部关闭:

struct GameInfo

    unsigned int m_totalTurns;
    unsigned int m_wins;
    unsigned int m_loses;
    unsigned int m_ties;
;

class GameInstance

private:
    GameInfo gameInfo;
public:
    GameInfo GetInfo() const;
;

这种方法仍然是安全的,但您不必编写烦人的 getter。

【讨论】:

【参考方案4】:

这里有关于何时/为什么应该使用 getter 和 setter 的相当好的讨论:SO Getters and Setters Question

但它通常值得使用它们,即使它只是用于内部使用,它确保当您访问这些值时,您以统一的方式进行操作,确保您在编辑它们时遵守您的规则应该如何修改它们。

基本上它有助于在大多数情况下使您的代码更清晰。

编辑: 我应该指出,在使用私有 getter 和 setter 时,它更多的是个人选择,所以没有真正的“错误”答案,除非有我不知道的事情

【讨论】:

以上是关于Setter 和 getter 的必要性的主要内容,如果未能解决你的问题,请参考以下文章

Lombok 写一个@Data更好还是@Getter+@Setter更好?

变量的定义及访问效率

关于@property()的那些属性及ARC简介

Java bean中布尔类型使用注意

getter和setter方法

iOS 开发:成员变量(属性,实例变量)的相关知识