擴展方法
如果想要對現(xiàn)有的類添加新的方法惧互,但是又不太可能去修改原有類的時候哎媚,我們就可以通過擴展方法進行擴展(當然,也有其他的方式可以達到目的)壹哺,java原生是不支持擴展方法的抄伍,熟悉其他語言的同學(xué)可能知道,例如:C#管宵、go截珍、kotlin等都是原生支持擴展方法的攀甚,那如果想在java中也要實現(xiàn)擴展方法,比如:“hello world”.print();實現(xiàn) 這樣的功能岗喉,該如何做呢秋度?
Manifold介紹
Manifold是一個java的編譯插件,其中包含了很多的功能钱床,其中擴展方法就是其中之一荚斯,更多的功能介紹可以參考官網(wǎng)以及源代碼
接下來我們簡單地通過代碼的方式看看manifold是如何實現(xiàn)擴展方法的。
- 首先查牌,添加依賴事期,參考pom.xml文件如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-ext-app</artifactId>
<version>0.1-SNAPSHOT</version>
<name>My Java Extension App</name>
<properties>
<!-- set latest manifold version here -->
<manifold.version>2022.1.14</manifold.version>
</properties>
<dependencies>
<dependency>
<groupId>systems.manifold</groupId>
<artifactId>manifold-ext-rt</artifactId>
<version>${manifold.version}</version>
</dependency>
</dependencies>
<!--Add the -Xplugin:Manifold argument for the javac compiler-->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>UTF-8</encoding>
<compilerArgs>
<!-- Configure manifold plugin-->
<arg>-Xplugin:Manifold</arg>
</compilerArgs>
<!-- Add the processor path for the plugin -->
<annotationProcessorPaths>
<path>
<groupId>systems.manifold</groupId>
<artifactId>manifold-ext</artifactId>
<version>${manifold.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
- 定義一個類,例如:StringExtension
package extensions.java.lang.String;
import manifold.ext.rt.api.Extension;
import manifold.ext.rt.api.This;
@Extension
public class StringExtension {
public static void print(@This String thiz) {
System.out.println(thiz);
}
@Extension
public static String lineSeparator() {
return System.lineSeparator();
}
@Extension
public static String sayHello(String name) {
return "hello " + name;
}
}
特別說明下:擴展的包的定義是有一定的限制纸颜,所有的擴展類必須是在extensions
包下面定義兽泣,后面加上要擴展的類的包,例如上代碼:extensions.java.lang.String
,在java9以及后續(xù)的版本中胁孙,我們還可以加上自己的模塊名稱唠倦,比如:com.test,那么擴展的包名就可以是:com.test.extensions.java.lang.String
,在java8中extensions
必須是根涮较。
擴展方法所在的類必須添加@Extension注解稠鼻,擴展方法必須是靜態(tài)的公共方法,而且第一個參數(shù)為:@This+擴展的類型+參數(shù)名稱狂票,如果是靜態(tài)的擴展方法那么需要在靜態(tài)方法上面加@Extension注解候齿,參數(shù)不再需要@This 進行限定,定義完成之后我們可以通過如下的方式進行調(diào)用了
"hello world".print();
System.out.println(String.sayHello("sherman"));
當然闺属,為了更棒的體驗毛肋,還是要在idea中裝一個插件Manifold
其他類型擴展
比如,我想針對Iterable<T>這個類型進行擴展屋剑,可以參考如下的代碼:
package extensions.java.lang.Iterable;
import manifold.ext.rt.api.Extension;
import manifold.ext.rt.api.Self;
import manifold.ext.rt.api.This;
import java.util.NoSuchElementException;
import java.util.function.Predicate;
@Extension
public class CollectionExtension {
public static <T> T first(@This Iterable<T> thiz, Predicate<T> predicate) {
for (T element : thiz) {
if (predicate.test(element)) {
return element;
}
}
throw new NoSuchElementException();
}
}
List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
Predicate<String> getFirst = s -> Objects.equals(s, "one");
String first = list.first(getFirst);
System.out.println(first);
Manifold已經(jīng)為我們提供了一些擴展
-
Collections
定義在manifold-io模塊中润匙,擴展了以下的類
- java.io.BufferedReader
- java.io.File
- java.io.InputStream
- java.io.OutputStream
- java.io.Reader
- java.io.Writer
-
Text
定義在manifold-text模塊中,擴展了以下的類
- java.lang.CharSequence
- java.lang.String
-
I/O
定義在manifold-io模塊中唉匾,擴展了以下的類
- java.io.BufferedReader
- java.io.File
- java.io.InputStream
- java.io.OutputStream
- java.io.Reader
- java.io.Writer
-
Web/JSON
定義在manifold-json模塊中孕讳,擴展了以下的類
- java.net.URL
- manifold.rt.api.Bindings
我們也可以將自己的擴展以包的形式提供出去,具體注意事項可以參考官方的文檔巍膘。