【问题标题】:When does it make sense to return this-reference?什么时候返回这个引用有意义?
【发布时间】:2010-10-09 13:33:10
【问题描述】:

目前我只能想到三个很好的理由返回 this 在(公共)方法中,即:

  1. (mmyers) 在实现 fluent 接口 时,例如

    public class X
    {
      ...
      public X enableValidation()
      {
        setValidation(true);
        return this;
      }
      ...
    }
    
  2. (Jon Skeet) 用于身份转换,例如

    public class X
    {
      ...
      public X toX()
      {
        return this;
      }
      ...
    }
    
  3. (Dave Ray) 在不可变对象上实现clone()copy()方法,例如

    @Immutable
    public class X
    {
      ...
      public X copy()
      {
        return this;
      }
      ...
    }
    

在面向对象语言中是否还有其他有用的场景可以让您从方法中返回thisself

【问题讨论】:

  • 哇!我不仅被引用了,我在 Jon Skeet 上面被引用了! (虽然我的名字拼错了,所以我猜它是均匀的。;))
  • 作为对我们谈话的回应,我添加了一个我正在描述的对象结构示例。
  • @eljenso:从我们之前的谈话来看,这有意义吗?
  • @eljenso:我认为是的..
  • @mmyers:对于拼写错误,我很抱歉,我最后一次编辑很匆忙,结果马虎了。

标签: language-agnostic oop


【解决方案1】:

采取以下实现。

public interface Monitorable {
   public Statistics getStatistics();
}

public interface MonitorManager {
   public Monitorable getMonitorable();
}

class MonitorableService implements Monitorable, MonitorManager {
   public Monitorable getMonitorable() {
      return this;
   }
}

// Meanwhile somwhere else...
MonitorManager manager = getMonitorManagerFromSomewhere();
Monitorable monitorable = manager.getMonitorable();

我承认这有点做作,但总体模式/信息应该很清楚。

这里我不需要知道 MonitorManager 是由 Application 类实现的。我也不需要知道 Monitorable 是由 Application 实现的。

这里使用多态来封装Application的实现细节。这不是公共课程。这是一种非常常见的模式,可以在各种各样的项目中看到。

【讨论】:

  • 首先,感谢您的回复。我现在可以更清楚地阅读您的代码,但我仍然没有得到一些东西。应用程序类在哪里?为什么声明了 Monitor 接口但没有使用? MonitorManager 的唯一功能是返回 Monitorable 吗?
  • 我认为您在这里表达的内容可以通过使用正确的类型来解决。 MonitorableService 的实例可以声明为 Monitorable 或 MonitorManager 或 MonitorableService(包括两者),具体取决于上下文。
  • 是的,MonitorManager 的契约已经用一个对象实现了,尽管有几个在起作用。实现细节对用户是隐藏的,这可以通过其他方式实现,但是像许多框架一样,以这种方式实现合约通常非常有用。
  • 你又说这是一种常见的模式。您甚至说过这是大多数 OO 系统的关键要求。所以也许你可以给我展示一两个使用这种模式的项目?
  • 好吧,我说我给出的例子是基本的,这个模式包含在使用“this”将对象传递给方法的过程中,你可能还记得,this 比“this.field”更有用”。我认为这里的模式很明显,而且很有用。您将在许多框架中看到它的示例。
【解决方案2】:

流畅界面的快速添加:

正如这篇“流畅界面的简单示例”文章(在 cmets 末尾)中提到的,:

使用继承和流畅的接口时,你会遇到困难,因为:

  • 使用多态方法打破你的调用链
  • 您绝对不希望通过在不需要它们的地方使用丑陋的强制转换和括号或在执行强制转换的子项中进行大量无用的覆盖来使您的界面不流畅

alt text http://withasmiletomeltathousandhearts.files.wordpress.com/2009/02/fluent_interfaces_order_class_hierarchy.jpg?w=300&h=255

在这个 article about a more robust pattern for complex (and yet fluent) hierarchy of classes 中,“this”用于返回基类“Builder”的实例,而用于具体类的 Builder 使用强制转换。

【讨论】:

  • 我知道,不是完全回答你的问题,但我发现这种“流畅”层次结构的模式很有趣。
【解决方案3】:

C++ 一直这样做是为了允许级联运算符。

例如 std::cout << "call 1" << "call2" << std::endl;

我认为这种级联效应流行的唯一语言是 C++。

【讨论】:

  • 我猜这属于流畅界面的类别(问题已经涵盖),这比我想象的更常见。
【解决方案4】:

如果您正在创建链接操作(但是这可能不是非常面向对象的 - 得墨忒耳法则等)。

示例(不是说它很有意义):

public class X 
{
   public X Add(int i) 
   { 
      this.Value += i; 
      return this;
   }

   public X Subtract(int i) 
   {
      this.Value -= i;
      return this;
   }

   public int Value 
   {
      get;
      set;
   }
}

new X().Add(4).Subtract(5).Value;

【讨论】:

  • 流畅的界面,已经在问题中涉及。不过,很高兴您同意这是退货的有效且有用的理由。
【解决方案5】:

不可变对象上的 clone() 或 copy() 方法的任何实现。

【讨论】:

    【解决方案6】:

    String.toString() :)

    更严肃地说,有类似的“转换为 [x]”场景,可以只返回“this”......但我想不出很多其他情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多