IntelliJ IDEA 復雜的重構技巧(二)
轉載
上次我說了一些 “復雜的重構技巧” ,講的是一些使用 IntelliJ 的簡單功能實現復雜的重構需求的技巧。 看到大家的反響之后我就感覺那個可能不大親民,因為很多人連 inline 這功能都不知道(那豈不是把 IntelliJ 用成了記事本), 於是我決定再寫一篇講講 IntelliJ 已經提供好了的一些復雜的重構功能。
這就不再是需要自己進行奇奇怪怪的操作的教程了,就會親民得多。
從方法中提取方法
這是用來快速復用一段代碼的功能,名叫 “Extract Method” 。
比如,我現在有這么一段業務代碼(順帶一提,這是在 Java 調用動態語言 API 時能使用的最健壯的處理數值類型的方法):
|
為了效率考慮,你決定不使用 subList(1, nodes.size()).forEach
而是使用 for
循環。
然后你突然發現,這個 “遍歷一個集合除了第一個元素之外的元素” 操作在你的代碼里面已經被調用了很多次了。
於是你決定貫徹 “非極端性 DRY 原則” ,把這坨代碼復用起來。
我們仔細觀察一下。
這坨代碼中,直覺上,我們希望可以通過形如
|
的代碼來一行處理這個操作的(不懂方法引用的請退群),但是這個 forEachExceptFirst
是不存在的。
所以我們想自己造一個。
這時候我們就應該使用 IntelliJ IDEA 提供的 Extract method
功能了。
首先選中那一堆代碼,然后按下 Ctrl+Alt+m,看到這么一個窗口。
然后我們在 “Name” 那一欄輸入 forEachExceptFirst
,也就是我們想提取的函數的函數名;然后回車。
我們可以看到,代碼變成了這樣:
|
我們可以看看它生成的這個 forEachExceptFirst
方法:
|
然后你就可以在其他地方使用這個方法了。
我們可以給它加上 JetBrains annotations:
|
當然加這么多意義不大,對 Node
類型的 @NotNull
注解是可以去掉的。
撤回這個操作的話,請使用上一篇博客所大量使用的 inline
功能。
從類中提取接口
比如,我們有這么一個 Java 類(最近突然覺得,對類型的注解應該比可見性修飾符更靠近類型(比如在一個方法中, 我就可以用這種方法來區分對返回類型的注解(比如 @NotNull
)和對方法本身的注解(比如 @Override
)), 所以就有了這么個把注解寫在可見性修飾符后面的奇怪的寫法,希望讀者不要介意這一點)。
|
代碼中省去了一些對文章不重要的細節。
然后我們可以在類名上右鍵,然后找到這個東西:
這樣我們會看到一個窗口,里面的東西還挺復雜的:
首先我們在 “Interface name” 那里填我們想抽取的接口的名字,比如剛剛的那個類 Marisa
,就很適合GensokyoManagement
(畢竟魔理沙是幻想鄉兩位城管之一嘛,又因為城管的翻譯是 Urban management
) 這個名字的接口。
然后我們希望把這三個方法都抽取到接口里面去,於是就勾選下面的三個方法。請根據實際需求勾選需要抽取的方法。
最后回車。
這時候 IntelliJ IDEA 會詢問你,是否 “盡可能在這個類被使用的地方,把這個類的類型改成接口的類型”。
這是一種很好的作法,比如我們會傾向於把
|
寫成
|
,對不對吖。
這里這個提示就是問你要不要這么換一波的。這個就看需求了,另外建議取消勾選下面的 “Preview usages to be changed”。
最后我們就提取出來了這么個玩意(這里只有三個方法所以生成的代碼很少,看起來不是很高大上, 如果你實現了一種操作比較多的數據結構(比如線段樹啊,各種圖啊樹啊)再這么來一波,就能生成一大坨):
|
然后我們就可以再寫其他類,比如:
|
然后讓 IntelliJ IDEA 自動生成之前那些方法,然后我們就可以愉快地寫實現啦。
接口與實現間的互相發送代碼
我們還有很多可以做的事情,比如我們現在給 Marisa
類加了新方法作為新功能,然后我們想給 Reimu
也加上, 並把這個方法作為 GensokyoManagement
的一個抽象方法之一(接口的方法是默認抽象的,別因為省了 abstract
修飾符就以為不是了):
|
我們可以這樣,在新方法上右鍵,然后這么選:
這樣我們會看到一個窗口,里面的東西不怎么復雜:
只需要勾選我們要送給接口(或者父類)的方法,然后回車就好了。
IntelliJ IDEA 會給你加上 @Override
修飾符,和生成新的抽象方法。
然后我們就可以跳到 Reimu
類,讓 IntelliJ IDEA 生成一個空實現,然后接着寫啦。
本文作者:ice1000
原文鏈接:http://ice1000.org/2017/12/25/IDEARefactoring2/
版權歸作者所有,轉載請注明出處