<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                in和out是一個對立面,其中**in代表泛型參數類型逆變,out代表泛型參數類型協變**。從字面意思上也可以理解,**in代表著輸入,而out代表著輸出。但同時它們又與泛型不變相對立,統稱為型變,而且它們可以用不同方式使用**。比如: ``` public interface List<out E> : Collection<E> {} ``` 這種方式是在聲明處型變,另外還可以在使用處型變,比如上面例子中sortWith方法。在了解了泛型變形的原理后,我們來看一下泛型變形到底在什么地方發揮了它最大的用處。 假設現在有個場景,需要將數據從一個Double數組拷貝到另一個Double數組,我們該怎么實現呢? 一開始我們可能會這么做: ``` fun copy(dest: Array<Double>, src: Array<Double>) { if (dest.size < src.size) { throw IndexOutOfBoundsException() } else { src.forEachIndexed{index, value -> dest[index] = src[index]} } } var dest = arrayOfNulls<Double>(3) val src = arrayOf<Double>(1.0,2.0,3.0) copy(dest, src) ``` 這很直觀也很簡單,但是學過泛型后的你一定不會這么做了,**因為假如替換成Int類型的列表,是不是又得寫一個copy方法**?所以我們可以對其進一步抽象: ``` fun <T> copy(dest: Array<T>, src: Array<T>) { if (dest.size < src.size) { throw IndexOutOfBoundsException() } else { src.forEachIndexed{index, value -> dest[index] = src[index]} } } var destDouble = arrayOfNulls<Double>(3) val srcDouble = arrayOf<Double>(1.0,2.0,3.0) copy(destDouble, srcDouble) var destInt = arrayOfNulls<Int>(3) val srcInt = arrayOf<Int>(1,2,3) copy(destInt, srcInt) ``` **通過實現一個泛型的copy,可以支持任意類型的List拷貝**。那么這種方式有沒有什么局限呢?我們發現,**使用copy方法必須是同一種類型,那么假如我們想把`Array<Double>`拷貝到`Array<Number>`中將不允許,這時候我們就可以利用上面所說的泛型變形了**。這種場景下是用協變還是逆變呢? ``` //in版本 fun <T> copyIn(dest: Array<in T>, src: Array<T>) { if (dest.size < src.size) { throw IndexOutOfBoundsException() } else { src.forEachIndexed{index, value -> dest[index] = src[index]} } } //out版本 fun <T> copyOut(dest: Array<T>, src: Array<out T>) { if (dest.size < src.size) { throw IndexOutOfBoundsException() } else { src.forEachIndexed{index, value -> dest[index] = src[index]} } } var dest = arrayOfNulls<Number>(3) val src = arrayOf<Double>(1.0,2.0,3.0) copyIn(dest, src) //允許 copyOut(dest, src) //允許 ``` 到這里你可能迷糊了,為什么兩種方式都允許?其實細看便能發現不同,**in是聲明在dest數組上,而out是聲明在src數組上,所以dest可以接收T類型的父類型的Array,out可以接收T類型的子類型的Array**。當然這里的T要到編譯的時候才能確定。比如: * in版本,T是Double類型,所以dest可以接收Double類型的父類型Array,比如`Array<Number>`。 * out版本,T是Number類型,所以src可以接收Number類型的子類型Array,比如`Array<Double>`。 所以in和out的使用是非常靈活的。當然上面我們也提到了使用了它們就會有相應的限制,這里我們就對泛型參數類型不同情況的特性及實現方式進行一下總結,如表所示。 :-: 表Kotlin與Java的型變比較 ![](https://img.kancloud.cn/f3/08/f308f952981728ed77c0416d07589c25_533x94.png) 前面我們所說的泛型變形或者不變都是在一種前提下的討論,那就是你需要知道泛型參數是什么類型或者哪一類類型,比如它是String或者是Number及其子類型的。**如果你對泛型參數的類型不感興趣,那么你可以使用類型通配符來代替泛型參數。前面已經接觸過Java中的泛型類型通配符“? ”,而在Kotlin中則用“*”來表示類型通配符**。比如: ``` val list: MutableList<*> = mutableListOf(1, "kotlin") list.add(2.0) //出錯 ``` 這個列表竟然不能添加,不是說好是通配嗎?按道理應該可以添加任意元素。**其實不然,`MutableList<*>`與`MutableList<Any? >`不是同一種列表,后者可以添加任意元素,而前者只是通配某一種類型,但是編譯器卻不知道這是一種什么類型,所以它不允許向這個列表中添加元素,因為這樣會導致類型不安全**。不過細心的讀者應該發現前面所說的**協變也是不能添加元素**,那么它們**兩者之間有什么關系呢?其實通配符只是一種語法糖,背后上也是用協變來實現的。所以`MutableList<*>`本質上就是`MutableList<out Any? >`,使用通配符與協變有著一樣的特性**。 當前泛型變形的另一大用處是體現于高階函數,比如Java 8中新增的Stream中就有其應用: ``` <R> Stream<R> map(Function<? super T, ? extends R> mapper); ``` 另外,**在責任鏈模式也會涉及高階函數對于泛型變形的應用**。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看