kotlin言語のoutとin

7128 ワード

ps:原文を読み、ソースコードを取得できます
kotlin言語ではoutはコヒーレントを表し、inはインバータを表す.コヒーレントとインバータはkotlin独自の概念ではなく、Java、C#のような概念があります.kotlin言語のoutとinを理解するために、Javaの汎用を例に挙げると、コンパイル時にタイプのセキュリティをチェックでき、すべての強制変換が自動的で暗黙的であることがメリットです.
1、Javaの中の?extends Tと?super T
1、1 ? extends T
ps:コードはAndroid Studioツールに書かれています
Javaファイル鳥Birdsを作成します.
public class Birds {
 private String name;
 public Birds(String name) {
 this.name = name;
 }
 public void flight() {
 System.out.println("  " + name + ",    ,    ");
 }
}

JavaファイルカラスクラスCrowを作成し、Birdsを継承します.
public class Crow extends Birds {
 public Crow(String name) {
 super(name);
 }
}

Javaファイルの汎用クラスTestBirdsを新規作成し、汎用TがBirdsのサブクラスであることを制限します.
public class TestBirds {
 public void actionBirds(List birds) {
 for (T bird : birds) {
 bird.flight();
 }
 }
}

プログラム入口でList listをパラメータとしてTestBirdsに渡すactionBirdsメソッドを試みた.
 List list = new ArrayList<>();
 TestBirds testBirds = new TestBirds<>();
 Crow crow = new Crow("  ");
 list.add(crow);
 
 /**
 *    list         
 */
 testBirds.actionBirds(list);

ここで分析すると、TestBirdsは汎用クラスであり、使用される前にTは不確定であり、使用後Tは確定であり、Birdsである.listをパラメータとしてactionBirdsメソッドに入力することは,List birds=listと同等であるが,List birds=listは成立せず,CrowはBirdsに継承されるが,birdsはBirdsタイプのオブジェクトのみを保存し,listはCrowタイプのオブジェクトのみを保存し,birdsとlistは何の関係もない.
TestBirdsクラスには、actionBirdsメソッドに基づいて修正されたactionBirds 2メソッドが追加されました.
 public void actionBirds2(List extends T> birds) {
 for (T bird : birds) {
 bird.flight();
 }
 }

プログラム入口でList listをパラメータとしてTestBirdsに渡すactionBirds 2メソッド;
 List list = new ArrayList<>();
 TestBirds testBirds = new TestBirds<>();
 Crow crow = new Crow("  ");
 list.add(crow);
 
 /**
 *    list         
 */
//        testBirds.actionBirds(list);
 
 testBirds.actionBirds2(list);

このときtestBirds.actionBirds 2(list)というコードのコンパイルが通過したことに気づきましたが、不思議な感じがしますか?ここで分析すると、listをパラメータとしてactionBirds 2に転送する方法は、リストextends Birds>birds=listに等しく、これは成立している.リストextends Birds>birdsは、集合記憶されているのはBirdsとBirdsのサブクラスオブジェクトであり、前回を限定しているが、list記憶されているのはBirdsサブクラスのオブジェクトであるため、コードコンパイルが通過し、それは成立している.上界ワイルドカード,extendsキーワードで宣言し,パラメータがT,またはTのサブクラスである可能性があることを示す.
1、2 ? super T
上記の既存のコードに基づいて、TestBirdsクラスにactionBirds 3メソッドを追加します.
 public void actionBirds3(List birds,List crows) {
 for (T crow : crows) {
 birds.add(crow);
 }
 }

プログラムエントリでTestBirdsのactionBirds 3メソッドの呼び出しを試みる.
 List list = new ArrayList<>();
 TestBirds testBirds = new TestBirds<>();
 Crow crow = new Crow("  ");
 list.add(crow);
 List birdsList = new ArrayList<>();
 testBirds.actionBirds3(birdsList,list);

ここまで来ると、actionBirds 3メソッドの最初のパラメータが赤色コンパイルエラーと報告されているのは、TestBirdsクラスオブジェクトをインスタンス化したときにTがCrowに置き換えられたためであり、birdsListはBirdsタイプのデータのみを格納し、actionBirds 3メソッドの最初のパラメータはCrowタイプのデータのみを格納しているため、2つは何の関係もないため、構文コンパイルエラーとなる.
TestBirdsにactionBirds 4メソッドを追加し、actionBirds 3に基づいて最初のパラメータを変更します.
 public void actionBirds4(List super T> birds,List crows) {
 for (T crow : crows) {
 birds.add(crow);
 }
 }

実パラメータが変わらない場合、TestBirdsのactionBirds 4メソッドをプログラムエントリで呼び出す.
 List list = new ArrayList<>();
 TestBirds testBirds = new TestBirds<>();
 Crow crow = new Crow("  ");
 list.add(crow);
 List birdsList = new ArrayList<>();
 
 /**
 *    birds         
 */
//        testBirds.actionBirds3(birds,list);
 testBirds.actionBirds4(birdsList,list);

このときTestBirdsを呼び出すactionBirds 4メソッドがコンパイルされていることがわかりました.分析してみましょう.actionBirds 4メソッドの最初のパラメータはList super T>birdsです.super Tは下限ワイルドカードであり、使用中に定義されるパラメータタイプがTまたはTの親を表し、birdsはTタイプとTの親のオブジェクトを格納する.TestBirdsをインスタンス化する過程で、CrowをTに置き換え、BirdsはちょうどCrowの親であり、TestBirdsのactionBirds 4メソッドを呼び出して最初のパラメータを渡す場合はList super Crow>birds=listに相当するので、コンパイルはパスする.
2、kotlinのoutとin
2、1 out
上に?extends Tのコードケースでは、TestBirdsクラスのactionBirds 2メソッドの最初のパラメータbirdsセットが追加されましたか?extends Tを制限し、forループでTの要素を取り出します.このような操作は読み取りです.extends Tはワイルドカードタイプの上界を限定しているので、安全に読み取ることができますが、データを変更することはできません.そこからしか読み取れないオブジェクトを生産者と呼ぶことができます.List extends T>このようなタイプの消費を行わない生産者は、タイプの運行の安全を保証し、これがコヒーレントである.kotlinでoutで表すと、kotlinの「out T」はJavaの「?extends T」に等しい.次にkotlinのoutキーワードを例に挙げます.
新しいkotlinクラスTestBirds 2を作成し、TestBirdsクラスactionBirds 2の効果と同じ関数を書きます.
class TestBirds2 {
 fun actionBirds2(birds: MutableList) {
 for (bird: T in birds) {
 bird.flight()
 }
 }
}

プログラムエントリでTestBirds 2のactionBirds 2関数を呼び出す.
 var testBirds2: TestBirds2 = TestBirds2()
 var crow: Crow = Crow("  ")
 var crowList: MutableList = mutableListOf(crow)
 testBirds2.actionBirds2(crowList)

2、2 in
上に?super Tのコードケースでは、TestBirdsクラスのactionBirds 4メソッドの最初のパラメータbirdsセットが追加されましたか?super Tを制限し、forループで2番目のパラメータcrowsのT要素を取り出し、birds集合にT要素を入れる.super Tはワイルドカードタイプの下限を限定するので、データを安全に修正することができます.つまり、T要素をbirdsセットに入れることができます.そこからしか修正できない対象を消費者と呼ぶことができます.List super T>のようなタイプで取得されたデータ型はObjectであり、意味がなく、生産を行わない消費者がタイプ運転の安全を保証すると考えられ、これがインバータである.kotlinではinで表され、kotlinの「in T」はJavaの「?super T」に等しい.次にkotlinのinキーワードを例に挙げます.
TestBirds 2クラスにTestBirdsクラスのactionBirds 4メソッドの効果と同じ関数を書きます.
 fun actionBirds4(birds: MutableList,crow: MutableList) {
 for (t: T in crow) {
 birds.add(t) 
 }
 }

プログラムエントリでTestBirds 2のactionBirds 4関数を呼び出す.
 var testBirds2: TestBirds2 = TestBirds2()
 var crow: Crow = Crow("  ")
 var crowList: MutableList = mutableListOf(crow)
 var birdsList: MutableList = mutableListOf()
 testBirds2.actionBirds4(birdsList,crowList)

2、3タイプの投影
上のoutとinの例は、TがBirdsに継承される限界があるため、使用には制限があります.ここではタイプ投影についてお話ししますが、タイプ投影を話す前にAnyについてお話しします.Anyはkotlin言語の祖先クラスで、JavaのObjectに似ていますが、Objectに等しいわけではありません.Anyにはequals、hashCode、toStringの3つの関数しかないからです.1つのクラスを汎用クラスとして宣言し、汎用タイプはout位置に現れるかin位置に現れるか、使用場所でコヒーレントまたはインバータに宣言することができ、このタイプをある面に投影して使用することに等しく、タイプ投影に属する.汎用クラスMutableListでは、本当にMutableListをインスタンス化する場合、Tの位置にinまたはoutを多く追加し、このタイプをある面に投影して使用することができる.すなわち、MutableListの読み出しデータ方法getまたは書き込みデータ方法addである.次に、MutableListの書き込みコードを例に挙げます.
 var mutableList: MutableList = mutableListOf("        ",2,3,4,5)
 var size: Int = mutableList.size - 1
 var any: Any? = null
 for (i: Int in 0 .. size) {
 any = mutableList.get(i)
 println(" " + (i + 1) + "any --" + any)
 }
 var mutableList2: MutableList = mutableListOf()
 mutableList2.add("        ")
 
 /**
 *    Int   ,     ,   mutableList2    in String   
 */
 mutableList2.add(2)

この文章はここまで書いて終わりました.技術のレベルが限られているので、文章の中に間違いがあるのは避けられません.皆さんの批判と指摘を歓迎します.