重构函数调用-Encapsulate Downcast封装向下转型十三

重构函数调用-Encapsulate Downcast封装向下转型十三

1.封装向下转型

1.1.使用场景

某个函数返回的对象,需要由函数调用者执行向下转型(downcast)。将向下转型动作移到函数中。

在强类型OO语言中,向下转型是最烦人的事情之一。之所以很烦人,是因为从感觉上来说它完全没有必要:你竟然越俎代庖地告诉编译器某些应该由编译器自己计算出来的东西。但是,由于计算对象类型往往比较麻烦,你还是常常需要亲自告诉编译器对象的确切类型。向下转型在Java特别盛行,因为Java没有模板机制,因此如果你想从集合之中取出一个对象,就必须进行向下转型。

向下转型也许是一种无法避免的罪恶,但你仍然应该尽可能少做。如果你的某个函数返回一个值,并且你知道所返回的对象类型比函数签名所昭告的更特化,你便是在函数用户身上强加了非必要的工作。这种情况下你不应该要求用户承担向下转型的责任,应该尽量为他们提供准确的类型。

以上所说的情况,常会在返回迭代器或集合的函数身上发生。此时你就应该观察人们拿这个迭代器干什么用,然后有针对性地提供专用函数。

1.2.如何做

  • 找出必须对函数调用结果进行向下转型的地方。
  • 这种情况通常出现在返回一个集合或迭代器的函数中。
  • 将向下转型动作搬移到该函数中。
  • 针对返回集合的函数,使用Encapsulate Collection (208)。

1.3.示例

下面的例子中,我以Reading表示“书籍”。我还拥有一个名为lastReading()的函数,它从一个用于保存Reading对象的vector中返回其最后一个元素

Object lastReading() {
    
    
  return readings.lastElement();
}

我应该将这个函数变成:

// 向下转型
Reading lastReading() {
    
    
  return (Reading) readings.lastElement();
}

当我拥有一个集合时,上述那么做就很有意义。如果“保存Reading对象”的集合被放在Site类中,并且我看到了如下的客户端代码:

Reading lastReading = (Reading) theSite.readings().lastElement()

我就可以不再把向下转型的工作推给用户,并得以向用户隐藏集合

 Reading lastReading = theSite.lastReading();
 class Site...
   Reading lastReading() {
    
    
       return (Reading) readings().lastElement();
   }

如果你修改函数,将其返回类型改为原返回类型的子类,那就是改变了函数签名,但并不会破坏客户端代码,因为编译器知道它总是可以将一个子类自动向上转型为超类。当然你必须确保这个子类不会破坏超类带来的任何契约。

猜你喜欢

转载自blog.csdn.net/m0_38039437/article/details/129745625