代码之家  ›  专栏  ›  技术社区  ›  Pablojim

总是使用get和set方法来访问类自己的成员字段是反模式吗?[副本]

  •  8
  • Pablojim  · 技术社区  · 15 年前

    这个问题已经有了答案:

    在Java类中,用其吸收器和设置器访问成员字段是否被认为是好的或不好的做法?

    例如哪个更好:

    public Order {
        private Agreement agreement;
    
        public Agreement getAgreement() {
        return agreement;
        } 
    
        public void process() {
           //should I use:
           getAgreement().doSomething();
           //Or:
           agreement.doSomething();
        }
    }
    

    一般来说,由于kiss原则,我认为直接访问字段是最好的,而且稍后有人可能会用不可预知的结果覆盖get方法。

    然而,我的同事们认为最好保持一个抽象层。对此有什么共识吗?

    11 回复  |  直到 15 年前
        1
  •  8
  •   toolkit    15 年前

    这里的核心问题是,直接字段访问不适合通过子类重写方法、AOP、动态代理等进行拦截。根据具体情况,这可能是好事也可能是坏事。我会说,在内部使用getter和setter不是反模式或模式。这是一件好事或坏事,取决于你所在班级的情况和设计。

        2
  •  9
  •   Zachary Murray    15 年前

    老实说,在我看来,这取决于你用它做什么。就个人而言,当有疑问时,我总是将额外的抽象级别留在那里,以防稍后在子类中需要重写它。很多时候,我都避免了重写类的痛苦,因为我让getter或setter打开了重写的大门。

    另一件事是,其他客户机/程序员可能需要以您还没有想到的方式使用您的类,例如,从数据库中拉出Agreement类。在这种情况下,当它们重写您的类时,您已经让它们(或者可能是将来的您)无痛地修改了数据的检索方式。

    因此,除非您绝对确定只有一种方法可以访问该字段,而且它是100%直接的,否则最好将值的检索和修改分离开来,以便在将来的某个时候可以避免重写困难。

        3
  •  7
  •   Andrew Hare    15 年前

    我认为类的公共接口表示围绕状态的封装,因此,即使类的其他工作也能从这种封装中获益。

    如果您已经用public get方法包装了一个字段,那么您这样做是有原因的。也许该方法中有逻辑可以延迟加载字段,或者提供审计跟踪。不管该方法的原因是什么,您的类也很可能需要该逻辑。

        4
  •  4
  •   lumpynose    15 年前

    在我看来,有些人将这个问题解释为外部使用的getter和setter;我对pablojim问题的解释是,它是在类内使用它们,而不是类直接访问其字段。(这是私人的。)

    从这个角度来说,我和杰里科和帕特洛斯在一起;除非有什么理由不这样做,否则我可以直接从班级内部访问。

        5
  •  2
  •   Janusz Daniel Rindt    15 年前

    在Java中保持抽象层是一件好事。

    问题是,所有直接访问成员变量而没有类注意到的代码都不受类的控制。

    因此,当您决定以一种方式编辑类时,在一个除法中用作示例的一个成员永远不应该是0,您必须能够确保该值仅以一种确保这一点的方式更改。因此,您将为此方法添加一个setter,并将成员更改为private。但是现在您需要更改在没有setter的情况下访问成员的所有代码。
    如果知道要从类外部更改值,则仅当不知道将变量设为私有时提供setter,如果以后需要访问,则可能提供getter或setter。

    如果在其他对象中有某些方法总是为成员使用get,那么它会得到一个反模式,然后执行一些计算,然后使用get。这表明成员应该在另一个类中,或者方法需要在这个类中。

    拥有一个getter和setter而不考虑它,因为每个成员都会破坏封装,这不是一个好的设计选择。对于MOR内部人士,请阅读 article

        6
  •  1
  •   Tamar    15 年前

    我现在正在研究一些让我更喜欢getter的东西:我们现在将部分属性移动到一个“属性包”中,这意味着您不能只引用变量。因此,除了更改getter,我们还需要更改引用该变量的所有位置。这是需要牢记的事情。

        7
  •  0
  •   Bob Somers    15 年前

    这取决于你使用getter和setter的目的。通常,当我需要健全地检查进入类的数据或输出的格式数据时,我会使用它们。在这方面,我确实使用getter和setter作为这个类和其他可能需要访问其数据的类之间的接口层。

    我倾向于编写我的内部代码,这样它就知道如何处理这个类的私有数据,所以使用它自己的getter和setter访问它通常是不必要的和不需要的。

    不过,这完全取决于如何使用getter和setter。

        8
  •  0
  •   patros    15 年前

    我的经验法则是,如果它们执行的操作比设置或返回值更复杂,请使用setter/getter。否则,不需要它,因为您可以修复由成员变量更改引起的任何问题。

        9
  •  0
  •   clemahieu    15 年前

    您是对的,因为为每个属性变量做所有额外的工作是很烦人的。为什么语言允许一些根本没有人允许的东西?然而,不允许直接属性访问有非常令人信服的原因。

    我更喜欢埃菲尔的统一接入原则。您不能分配给属性,属性和函数的访问方式相同:

    class EXAMPLE
    feature
      variable: INTEGER
      variable_function: INTEGER
        do
          result := 4
        end
      variable_two: INTEGER assign variable_assign
      variable_assign (in: INTEGER)
        do
          variable_two := in
        end  
    end
    
    feature
    test
    local
      test: EXAMPLE
      value: INTEGER
    do
      create test
      value := test.variable  -- Valid
      value := test.variable_function  -- Valid and same even though it's a function
      test.variable := value -- Invalid
      test.variable_two := value -- Valid, an explicit setter is defined
    end
    
        10
  •  0
  •   Grimarr    15 年前

    我认为这是一个需要逐案考虑的问题。在整个类代码中使用getter会使它复杂化,并且可能会使它稍微慢一点。然而,它也使得它更具可扩展性和可重用性。

    我通常所做的就是使用getter,如果我能放弃任何可能有人想用另一个来覆盖getter的原因。如果这是一个如此简单,根本没有意义的东西,我通常不使用getter。

    如果编写代码来访问不带getter的变量,请考虑将getter函数设为“final”。这样,就不会有人试图重写您的代码,并撕掉他的头发,想知道为什么它不能工作。(请注意,Spring和Hibernate代理可能会使这成为一个坏主意。)

        11
  •  -1
  •   Stack Overflow is garbage    15 年前

    为了使它成为反模式,它必须是绝对有害的。我不明白在定义getter和setter时可能有什么坏处。最多,这是浪费时间(和打字),这使得它没有意义,但不是一个反模式。