例如,有一個多載方法:
public void setBorder(Color color) { ... }
public void setBorder(String colorName) { ... }
public void setBorder(Image image) { ... }
public void setBorder(File imageFile) { ... }
但是如果我想多載一個稍微不同的方法,就會有太多類似的方法:
public void setBorders(Color colorTop, Color colorRight, Color colorBottom, Color colorLeft) { ... }
public void setBorders(String colorTopName, Color colorRight, Color colorBottom, Color colorLeft) { ... }
public void setBorders(Image imageTop, Color colorRight, Color colorBottom, Color colorLeft) { ... }
/* ... */
public void setBorders(File imageTopFile, File imageRightFile, File imageBottomFile, Image imageLeft) { ... }
public void setBorders(File imageTopFile, File imageRightFile, File imageBottomFile, File imageLeftFile) { ... }
在另一方面,我不希望使用Object something與something instanceof這里。那么如何為這里的每個引數制作幾種正確的資料型別呢?
uj5u.com熱心網友回復:
您正在談論可以通過不同方式指定/實作的數量,因此您可以創建這樣一個類。
這提供:
- 一個型別/類/類別過于通用的概念
- 在幾個使用點避免許多甚至可能不完整的多載
所以:
public void setBorder(Border border) { ... }
public void setBorders(Border... borders) { ... }
public class Border {
public Border(Color color) { ... }
public Border(String colorName) { ... }
public Border(Image image) { ... }
public Border(Path imageFile) { ... }
}
public class Border {
...
public static Border fromColor(Color color) { ... }
public static Border fromName(String colorName) { ... }
public static Border fromImage(Image image) { ... }
public static Border fromPath(Path imageFile) { ... }
}
第二個版本是工廠方法的額外步驟。這允許不回傳 Border,而是回傳 Border 的專門子項。
當然,您可以創建自己的邊框實作:
class CssBorder extends Border { ... }
因此,您無需在一處同時指定所有變體。
uj5u.com熱心網友回復:
你的問題的直接答案非常簡單:不。沒有做不到,不可能。
Java 沒有你想要的;沒有選項可以撰寫交集型別,也沒有選項可以讓 java 在這里為您提供各種所需選項的組合爆炸。
所以我們需要發揮創造力;有許多選項可以滿足您想要什么的總體思路,但實際上并不是您特別要求的。
超載
你必須要接受(4種不同型別File,Image,String,和Color),為每4個引數。即4*4*4*4= 256 種方法。您可以將它們全部撰寫(糟糕!),或者您可以使用代碼生成工具為您生成它們。想必您不希望每次更改某些內容時都重新生成它,因此將代碼生成集成到構建程序中:Annotation Processors。
這是可能的。但是很復雜,我真的不認為你會想要這個。單個類檔案中的方法數量是有限制的,整個 Java 社區都不會這樣做。因此,生態系統中提供的工具并不期望它,因此不會對此表現“很好”。舉個簡單的例子:如果你真的要在這里進行 256 次多載,任何嘗試在這個方法上自動完成都會在下拉串列中顯示所有 256 種方法,并且可能對你的 IDE 有顯著的減慢效果,作為作者代碼完成代碼沒有考慮這種情況。
因此,我強烈建議反對這個計劃。
密封型別和包裝
Java16 直接帶來了密封型別,但即使沒有 java16,您也可以通過使用建構式的訪問控制來有效地擁有它們。
做一個型別,我不知道Border,也許。這種型別沒有公共建構式;它只有 4 個創建邊框的靜態方法:
public class Border {
private Border(...) {}
public static Border ofColor(Color color) { ... }
public static Border ofImage(Color color) { ... }
...
}
然后您撰寫 1 個setBorders帶有 4 個Border引數的方法,僅此而已。人們會這樣稱呼它:
foo.setBorders(Border.ofColor(BLACK), Border.ofImage(leftImage), ...);
鑒于只有 4 個ofX方法,而且它們是創建 Border 物件的唯一方法,因此這是呼叫此方法的唯一方法。
冗長有一個小問題;Border.ofColor(Color.BLACK)有點多余,與更短的Color.BLACK. 這是不幸的。人們可以靜態匯入這些ofX方法,結果可能會ofColor(Color.BLACK)更好一些。
建設者
即使使用密封型別/包裝器的“修復”,也需要記住邊框的順序。是不是像 CSS 那樣按頂部、右側、機器人、左側排序?或者是別的什么?是的,IDE 會有所幫助,但仍然如此。建設者解決了這兩個問題。您仍然需要 17 種方法,但這比 256 種要好。
例子:
public SetBordersBuilder setBorders() {
return new SetBordersBuilder();
}
public static class SetBordersBuilder {
private SetBordersBuilder() {}
public left(Image borderImage) { ... }
public left(String borderColorName) { .... }
// same for top, right, and bottom.
public void go() {
// actually sets the borders.
}
}
要使用它,可以去:
foo.setBorders()
.left(Color.BLACK)
.top(someImage)
.. etcetera
.go();
僅運行時檢查
撰寫一個方法,給它們 4 個型別為 的引數Object,然后繼續進行instanceof。這是簡陋的 API:它缺乏可發現性。僅閱讀簽名(例如,通過閱讀自動完成對話框)我不知道。這是一個有點神秘的方法呼叫:我傳入了 4 個邊框,一個邊框可以是……任何物件?奇怪的。如果不深入研究檔案,很難知道我可以傳遞什么型別的物件以及這可能意味著什么(我怎么知道傳遞字串有效并且意味著字串被解釋為邊框顏色的名稱?),如果我誤解并傳遞 setBorders 方法不理解的型別,直到我運行該代碼并收到例外時,我才會知道它。如果我得到一個紅色波浪下劃線作為一種型別,以及我稱之為這件事的指導,那就更好了。因此,不推薦。
我的建議?建設者解決方案,放下手。
uj5u.com熱心網友回復:
public class Main implements Context {
// YOU NEED ONLY ONE METHOD (NO NEED TO OVERLOAD MULTIPLE ONES)
public void setBorders(BorderBuilder borderBuilder) {
borderBuilder.setBorder(this);
}
}
interface BorderBuilder {
void setBorder(Context context);
}
public class FourColorBorderBuilder implements BorderBuilder {
private Color top;
private Color right;
private Color bottom;
private Color left;
@Override
public void setBorder(Context context) {
// impl
}
public FourColorBorderBuilder withTopColor(Color top) {
this.top = top;
return this;
}
public FourColorBorderBuilder withRightColor(Color right) {
this.right = right;
return this;
}
public FourColorBorderBuilder withBottomColor(Color bottom) {
this.bottom = bottom;
return this;
}
public FourColorBorderBuilder withLeftColor(Color left) {
this.left = left;
return this;
}
}
public class StringAndThreeColorBorderBuilder implements BorderBuilder {
private String topName;
private Color right;
private Color bottom;
private Color left;
@Override
public void setBorder(Context context) {
// impl
}
public StringAndThreeColorBorderBuilder withTopNameColor(String topName) {
this.topName = topName;
return this;
}
public StringAndThreeColorBorderBuilder withRightColor(Color right) {
this.right = right;
return this;
}
public StringAndThreeColorBorderBuilder withBottomColor(Color bottom) {
this.bottom = bottom;
return this;
}
public StringAndThreeColorBorderBuilder withLeftColor(Color left) {
this.left = left;
return this;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/344090.html
標籤:爪哇
