【问题标题】:What is the best practice for using "get" in method names?在方法名称中使用“get”的最佳实践是什么?
【发布时间】:2023-04-01 21:09:01
【问题描述】:

我注意到在 Java(包括 C#)的许多地方,许多“getter”方法都以“get”为前缀,而许多其他方法则没有。我从未注意到 Sun 似乎遵循的任何模式。在 getter 方法名称中使用“get”有哪些准则或规则?

【问题讨论】:

  • 在C#中,你应该更好地使用属性,它封装了get和/或set,让用户感觉就像在使用一个字段。

标签: methods getter names


【解决方案1】:

归结为语义。是的,C# 具有“属性”,它为您提供了一个 get/set 'method' 存根......但是 .NET Framework 中以“Get”开头的函数(......“方法”......)应该提示开发人员意识到某些操作的发生只是为了获得某些结果。

您可能认为这很奇怪,并说“为什么不直接使用返回类型来提示人们呢?”,答案很简单。考虑以下方法:

public Person CreatePerson(string firstName, string lastName) {...}

仅通过该方法的名称,您可能会想到其中涉及数据库活动,然后将返回一个新创建的“人”。

但是,这个呢:

public Person GetPerson(string firstName, string lastName) {...}

仅通过那个方法的名称,您就可以假设正在从数据库中100%“安全”地检索一个人。

您永远不会多次调用“CreatePerson”...但是您应该始终感到安全地调用“GetPerson”。 (它不应影响应用程序的“状态”)。

【讨论】:

  • 我知道在 C# 中函数通常以大写字母开头。这也意味着您需要编写类似public Person Person(string firstname) {...} 的东西——读起来不太好(如果它甚至可以编译?还没有使用C#)。在我见过的任何其他编程语言(public Person person(string firstname) {...})中或多或少地使用小写函数名称会带来很多混乱,也意味着不再需要get-前缀......所以你的论证是 C# 特有的。
  • @mozzbozz:在 C# 中,我们不使用名词作为方法名称。我们使用动词或带动词的术语来描述方法正在执行的操作。 “GetPerson”、“SetPerson”、“UpdatePerson”、“初始化”、“HighlightWords”。所以没有问题。发生您所描述的唯一情况是使用属性名称。它将使用大写名词。属性将被称为public Person Person { get; set; } 要记住的另一件事是,c# 具有属性作为特性,而 java 没有(您使用方法,对吗?)。因此,语言在这方面是完全不同的。
【解决方案2】:

我个人喜欢以下规则:

  • 只要值可以通过相应的set 方法直接修改,请使用get 前缀
  • 在值无法直接设置为属性的情况下删除 get 前缀(即没有等效的 setXXX 方法)

第二种情况的基本原理是,如果该值不是真正的用户可设置的“属性”,那么它不应该需要一对 get/set 方法。一个暗示是,如果遵循这个约定并且您看到一个 getXXX 方法,那么您也可以假设存在一个 setXXX 方法。

例子:

  • String.length() - 由于字符串是不可变的,因此长度是只读值
  • ArrayList.size() - 添加或删除元素时大小会发生变化,但不能直接设置

【讨论】:

  • 我读了你的回答,这条规则真的引起了我的共鸣。谢谢!
【解决方案3】:

Java中的“get”和“set”前缀对最初用作表示java bean的约定。后来,它变成了一种封装约定,因为 Java 不像 C# 那样没有适当的属性。

【讨论】:

    【解决方案4】:

    Java 中的最佳实践是对属性使用 get 和 set 前缀。

    框架、标签库等会寻找带有这些前缀的方法并将它们用作属性。

    所以,如果你有这样的 java 类...

    public class User{
        private String name;
        public String getName(){ return name;}
        public void setName(String name){ this.name = name; }
    }
    

    .. 使用 struts-tags(或任何其他基于 ognl 的标签库),您将使用 user.name 访问 name 属性。

    Spring 框架也在 xml 配置文件中使用此约定。

    【讨论】:

      【解决方案5】:

      Java(尚)不支持属性。 getter 和 setter 是解决这个问题的障碍。其他语言 - 包括 C# - 支持属性,您应该使用这些来代替。这也不仅仅是一个“最佳实践”:C# 中的序列化将依赖于属性,而不是 getter 和 setter,因此如果您需要序列化类,不使用属性可能会在未来导致各种问题。

      属性的优点是它们使代码更具可读性。类似的东西

      obj.setX(10);
      

      在Java中,变成

      obj.X = 10;
      

      然而在幕后,X 是一种方法,而不是一个变量,因此可以执行脏输入检查等。

      【讨论】:

        【解决方案6】:

        过去确实是这样,API 经常暴露只读属性而没有 get 前缀:String.length(),甚至更新的 Buffer.capacity() 都是合理的例子。

        这样做的好处是减少了绒毛。缺点是任何试图根据约定自动确定属性的东西都不会发现它们。我个人倾向于在包含前缀方面犯错。

        当然,在 C# 中,这几乎是无关紧要的,因为无论如何都有“真正的”属性 :)

        【讨论】:

        • 因此,如果您想返回一些数据(只读)并且面临在只读属性、名称以“Get”开头的函数和名称不以“得到”,请说明你会选择哪个?
        • @toddmo:在 Java 中,我通常使用get。鉴于上下文是 Java,与名称以“get”开头的函数相比,我不确定您所说的只读属性是什么意思...
        • @toddmo:啊,那还不清楚。在 C# 中,它几乎总是一个属性。
        【解决方案7】:

        这取决于。它通常是冗余信息,即使在没有属性的语言中也是如此。

        在 C++ 中,通常提供 Attr() 函数的两个重载,而不是 getAttr()/setAttr() 对: 无效属性(Foo f); // 设置器 Foo Attr(); // 获取器

        在 Java 中,通常的做法是为 get/set 添加前缀。 我不得不说最好的做法是使用你的语言的标准。在 Java 中,人们希望看到 get/set 前缀,因此省略它们可能会使人们感到困惑,即使它们并非绝对必要。

        【讨论】:

          【解决方案8】:

          只是一个简短的附录:另一个约定是布尔字段的 getter 以“is”而不是“get”为前缀,例如bool isEnabled() { return enabled; }

          【讨论】:

            【解决方案9】:

            Objective C 2.0 也使用属性,使用相同的点语法。

            在此之前,它对 getter 和 setter 使用了稍微不同的命名方案(当然,它仍然可以与属性一起使用,或者用于普通的旧属性)。

            value = [obj attr];
            
            [obj setAttr:value];
            
            [obj getAttr:&value];
            

            也就是说,get 的使用方式不同。它不返回值,而是将结果存储在传入的变量中。

            典型的getter 与属性同名,setter 是以set 为前缀的属性(按照Java 的约定)。这些约定由 KVO(Key-Value Observation)系统使用,因此应遵守。

            【讨论】:

              【解决方案10】:

              13 年后,我相信这个问题值得重新审视。当然,随着时间的推移,有很多 stackoverflow 问答(甚至这里有一些很好的答案)、文章和博客文章都得出了相同的结论,但最后,我认为,我们从 Brian Goetz 本人那里得到了一个相当直截了当的答案:

              “JavaBeans 命名约定*是一个有点不幸的故事,”他继续说道。 “对于通用开发来说,这是一个糟糕的惯例。这是在可视化编辑器中命名可视化组件的一个相当有针对性的约定,您可以在其中将按钮和标签以及类似的东西拖放到画布上,并且您可以编辑关于前景色和字体以及什么的属性表有你,可以通过反思发现。”

              Goetz 解释说,命名约定是构建这些 UI 组件的好方法——事实证明,这并不是一个关键的 Java 用例。 “然而,不知何故,我们继续使用该命名约定,尽管它与大多数业务领域对象的匹配度很差。”

              ——https://blogs.oracle.com/javamagazine/java-architects-loom-panama-valhalla#anchor_4

              * - 基本上是getX/setX 约定问题

              【讨论】:

                猜你喜欢
                • 2010-09-05
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2022-01-01
                • 1970-01-01
                • 2018-03-13
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多